Even if performance is not a critical requirement for the current project, and is not even marked as a requirement, it is often difficult to ignore performance issues, because you may think that ignoring performance issues will make you a "bad engineer." Developers often write small benchmark programs to measure the performance of one method relative to another by writing High-performance code as a target. Unfortunately, as you can see in the "Dynamic compilation and performance measurement" article written by December, commenting on the performance of a given idiom (idiom) or structure in the Java language is much more difficult than other statically compiled languages.
A flawed micro-benchmark
After I published the October article, "a more flexible and scalable locking mechanism in JDK 5.0," a colleague sent me a synclocktest benchmark (shown in Listing 1), which is said to judge synchronized and the new Reentrantlock class. Faster. " After running the benchmark on his laptop, he made a different conclusion to the article that the synchronization was faster and gave his benchmark as "evidence". The whole process-the design, implementation, implementation, and interpretation of the micro-benchmarks are flawed in many ways. In fact, my colleague is a very smart guy, and the benchmark also spent a lot of effort, see how difficult this kind of thing.
Listing 1. Defective Synclocktest micro-benchmarks
interface Incrementer {
void increment ();
}
Class Lockincrementer implements Incrementer {
Private long counter = 0;
Private lock lock = new Reentrantlock ();
public void Increment () {
Lock.lock ();
try {
++counter;
finally {
Lock.unlock ();
}
}
Class Syncincrementer implements Incrementer {
Private long counter = 0;
public synchronized void increment () {
++counter;
}
Class Synclocktest {
static long test (Incrementer incr) {
Long start = System.nanotime ();
for (long i = 0; i < 10000000L; i++)
Incr.increment ();
Return System.nanotime ()-Start;
}
public static void Main (string[] args) {
Long synchtime = Test (new Syncincrementer ());
Long locktime = Test (new Lockincrementer ());
System.out.printf ("Synchronized:%1$10d\n", synchtime);
System.out.printf ("Lock:%1$10d\n", Locktime);
System.out.printf ("lock/synchronized =%1$.3f",
(Double) locktime/(double) synchtime);
}
}
Synclocktest defines two implementations of an interface and uses System.nanotime () to calculate the time that each implementation runs 10,000,000 times. In the case of thread safety, each implementation adds a counter, one implementation uses built-in synchronization, and the other implements the new Reentrantlock class. The aim is to answer the following questions: "Which is faster, synchronized or Reentrantlock?" "Let's see why this seemingly no problem benchmark has not succeeded in measuring what you want to measure, or even measuring anything useful," he said.