TOC

Best practices of writing performant java programs

Adamansky Anton

Best practices of writing performant java programs

Basic performance tuning priciples

Premature Optimization

Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. Donald Ervin Knuth

GUI programs traits

Major steps to tune program performance

  1. Choose application metrics/objective function (avg resp time, ops/sec transaction/sec, ...)
  2. Locate relevant application/environment aspects what can be tuned.
  3. Change it!
  4. Evaluate objective function/metric values.
  5. Go to step 2. in the case of unacceptable evaluation results.

Document every iteration of this workflow in order to resolve non-trivial performance dependencies.

Casuses of performance problems

  1. IO routines (Network, HDD)
  2. Synchnozation and locking contention
  3. Overdesigned application / Excessive logging / ...
  4. Improper algorithms / data structures
  5. Lack of RAM/Not tuned GC / Page faults. ⇧ Goto 1.
  6. Lack of proper data caching / Excessive caching
  7. A poor hardware performance

Casuses of performance problems (CPU)

Problem Possible cause
User-space CPU consumption Application or JVM, Objects serialization
Kernel-space CPU consumption Locking, native libraries
Idle CPU IO, Locking, Thread pools settings

Sycnronization tips

Synchnozation and locking contention

Read-Write Locks

Read-Write Locks

pros: cons:

Concurrency tips: java.util.concurrent.atomic.* primitives

AtomicInteger ai = new AtomicInteger(10);
ia.getAndIncrement(1); //Atomically increments by one the current value.
 public final int getAndIncrement() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))
                return current;
        }
    }

CAS — Compare-And-Swap

public class SimulatedCAS {
    private int value;

    public synchronized int getValue() { return value; }

    public synchronized int compareAndSwap(int expectedValue, int newValue) {
         int oldValue = value;
         if (value == expectedValue)
             value = newValue;
         return oldValue;
     }
}

CAS — single machine instruction CMPXCHG since Intel 486.

Implement the java spin-lock using CAS

volatile int i = 0;
while (i == 1); //nop
i = 1;

....

i = 0;
         
What wrong with this code?

java.lang.String

Strings are fundamental elements of any java program and have huge impact on overall application performance. Why?

SITES BEGIN (ordered by live bytes) Fri Sep  6 11:26:25 2013
          percent          live          alloc'ed  stack class
 rank   self  accum     bytes objs     bytes  objs trace name
    1 24,53% 24,53%   6854712 285613  15251928 635497 300728 char[]
    2 24,53% 49,06%   6854712 285613  15251928 635497 300729 java.lang.String

java.lang.String

Java 1.6 String non static attributes:

java.lang.String

Java 1.7.0_06+ String non static attributes:

java.lang.String.intern()

Several String objects with equal value point to single String object resided in string pool.

Uniformly slow code

Your code slow? Profiling does't work anymore. Why?

The Wrong Use of Logging

    void foo(int arg1) {
        log.log(Level.FINE, "Calling foo with arg1=" + arg1);
    }
        

VS

    void foo(int arg1) {
        if (log.isLoggable(Level.FINE)) {
            log.log(Level.FINE, "Calling foo with arg1=" + arg1);
        }
    }