JDK 1.3 with Hotspot runs my ImageJ "Particles" benchmark 4 times
slower. This benchmark measure the size and location of 5097 objects
in a 2000x1000 binary image. Tests were run on a 400Mhz Pentium
and on a 400Mhz G3 Mac. ImageJ, including full source, is available
from "http://rsb.info.nih.gov/ij/". Times are in seconds.
50 MS JVM
119 MRJ 2.2
163 JDK 1.1.8
163 Netscape 4.5
183 JDK 1.2
223 JDK 1.3 (-classic)
244 Sun JDK 1.2.2 for Linux (190 with JIT)
640 IBM JDK 1.1.8 for Linux
769 JDK 1.3
To run the benchmark:
1) Run ImageJ
2) Open the test image using File/Open Samples/Particles.
3) Check "Area" and "Centroid" in Analalyze/Set Measurements.
4) Select Analyze/Analyze Particles.
5) Check "Display Results" and then click "OK".
What does MRJ stand for?
<remainder snipped>
Actually, the problem with the ImageJ application is in the code,
not in the VM. By commenting out exactly one statement, my
results were as follows:
JDK1.3 VM with Hotspot: 29.7 secs
JDK1.3 VM classic: 67.9 secs
Note that the Hotspot VM run is nearly twice as fast as Wayne's
best run.
Here's the code from the analyzeParticle() method of the
ParticleAnalyzer class:
void analyzeParticle(int x, int y, ImageProcessor ip) {
int counter = 0;
Wand wand = new Wand(ip);
wand.autoOutline(x, y, level1, level2);
if (wand.npoints == 0) {
IJ.write("wand error: " + x + " " + y);
return;
}
Roi roi = new PolygonRoi(wand.xpoints,wand.ypoints,
wand.npoints, imp,true);
if ((counter % 100) == 0) System.gc();
Rectangle r = roi.getBoundingRect();
ip.setRoi(r);
if (r.width > 1 && r.height > 1)
ip.setMask(roi.getMask());
ip.setColor(fillColor);
ImageStatistics s = new ByteStatistics(ip, measurements,
calibration);
ip.fill();
boolean include = true;
if (excludeEdgeParticles && (r.x == 0 || r.y == 0 ||
r.x + r.width == width ||
r.y + r.height == height))
include = false;
if (s.pixelCount>=minSize && s.pixelCount<=maxSize && include){
rt.incrementCounter();
rt.addValue(areaIndex, s.area);
rt.addValue(xIndex, s.xCentroid);
rt.addValue(yIndex, s.yCentroid);
if (showOutlines)
drawOutline(roi, rt.getCounter());
if (showResults) {
analyzer.displayResults(s, roi);
//IJ.write(IJ.d2s(rt.getCounter(),0)+
//" \t"+IJ.d2s(area,0));
}
}
}
The method creates an int called 'counter'. This value is never
incremented.
The method then checks
counter % 100 == 0
which is always true. When true the method calls System.gc().
The net effect is that every call to analyzeParticle() results is
a call to System.gc(). The 1.3 VM has a completely new garbage
collector, whose behavior is different than the previous GCs,
which results in the poor performance of this 'benchmark'. Any
optimization gains from Hotspot are dwarfed by thousands of
unnecessary calls to System.gc().
This example is just one more reason to *never* use the
System.gc() method. Leave garbage collection to the VM. It is
in a far better position to know when GC can and should be
performed. Only when you have a provable 'too many dead objects'
problem should you even consider calling System.gc().
Wayne, please comment out this line:
if ((counter % 100) == 0) System.gc();
in your code and report back your results.
Jim S.
* Sent from RemarQ http://www.remarq.com The Internet's Discussion Network *
The fastest and easiest way to search and participate in Usenet - Free!
<code snipped>
> The method creates an int called 'counter'. This value is never
> incremented.
>
> The method then checks
>
> counter % 100 == 0
>
> which is always true. When true the method calls System.gc().
> The net effect is that every call to analyzeParticle() results is
> a call to System.gc(). The 1.3 VM has a completely new garbage
> collector, whose behavior is different than the previous GCs,
> which results in the poor performance of this 'benchmark'. Any
> optimization gains from Hotspot are dwarfed by thousands of
> unnecessary calls to System.gc().
>
> This example is just one more reason to *never* use the
> System.gc() method. Leave garbage collection to the VM. It is
> in a far better position to know when GC can and should be
> performed. Only when you have a provable 'too many dead objects'
> problem should you even consider calling System.gc().
>
> Wayne, please comment out this line:
>
> if ((counter % 100) == 0) System.gc();
>
> in your code and report back your results.
>
> Jim S.
I've uncovered further proof that the call to System.gc() is the
culprit. If you wrap the System.gc() call like this:
long start = System.currentTimeMillis();
System.gc();
System.out.println("Elapsed time to GC: " + (System.currentTimeMillis()
- start));
When you run this code against a 1.2 VM you'll see alot of zeros and an
occasional 10ms for GC. If you run it under the 1.3 VM, you'll see a
consistent stream of 150-300ms GC elapsed times for *every* call to
System.gc(). This indicates to me, that in the 1.3 VM the GC makes more
of an effort to collect (in response to a request) than it does in the
1.2 VM.
Jim S.
-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 80,000 Newsgroups - 16 Different Servers! =-----
Out of interest Jim, could you try running that same code with 1.3 with
the -Xincgc switch on?
--
Jon Skeet - sk...@pobox.com
http://www.pobox.com/~skeet/
<snip>
>
> Out of interest Jim, could you try running that same code with
> 1.3 with the -Xincgc switch on?
>
No discernable difference. Still averages 150ms per GC call. My
statement above saying 150-300 was incorrect (I was guessing from
memory last night). Re-running the program this morning shows
the 150ms average with and without the -Xincgc option.
I removed the unnecessary calls to System.gc() and redid all the tests.
The "-classic" option doesn't seem to work anymore so I wasn't able to get
a JDK 1.3 classic result.
24 Netscape 4.5
24 MS JVM
28 JDK 1.3
30 JDK 1.2
35 MacOS Runtime for Java 2.2
39 JDK 1.1.8
60 Sun JDK 1.2.2 for Linux
70 IBM JDK 1.1.8 for Linux
This benchmark measure the size and location of 5097 objects
in a 2000x1000 binary image. Tests were run on a 400Mhz Pentium
and on a 400Mhz G3 Mac. ImageJ, including full source, is available
from "http://rsb.info.nih.gov/ij/". The updated version is 1.17i. Times
are in seconds.
To run the benchmark:
1) Run ImageJ
2) Open the test image using File/Open Samples/Particles.
3) Check "Area" and "Centroid" in Analalyze/Set Measurements.
4) Select Analyze/Analyze Particles.
5) Check "Display Results" and then click "OK".
-wayne
That's a little more like it. As a further test, I'd suggest having it
run the analyzeParticle method multiple times as well, or tracking the
time spent in each analyzeParticle() call. For me, this shaved 1-2
seconds off the total analyze time when running the test with the
'Display results' checkbox unchecked. On a ~4 second run, shaving a
second is significant.
BTW the '-classic' option is still available in the JDK tree, but not
the JRE tree. Windows finds the JRE 'java.exe' before the JDK
'java.exe' so it seems like the -classic option is broken. You can get
the -classic option working by doing something like this:
C:>D:\jdk1.3\jre\bin\java -classic ij.ImageJ