ln("*** Testing (Easy) ***");
for (int i = ZERO; i < CYCLES; ++i)
bench();
}
/**
* Benchmark controller for "Easy" tests.
*/
static void bench ()
{
t = new MethodEasy();
new HelperD().polyEasyF(1);
consume(Helper.x);
startBench("Interface: ");
do { t.benchInterface(); } while (!checkEnd());
endBench();
startBench(" TrulyPoly: ");
do { t.benchTrulyPoly(); } while (!checkEnd());
endBench();
startBench(" Poly: ");
do { t.benchPoly(); } while (!checkEnd());
endBench();
startBench(" Virtual: ");
do { t.benchVirtual(); } while (!checkEnd());
endBench();
startBench(" Final: ");
do { t.benchFinal(); } while (!checkEnd());
endBench();
startBench(" Static: ");
do { t.benchStatic(); } while (!checkEnd());
endBench();
System.out.println();
}
}
--- MethodBench.java
import java.text.DecimalFormat;
import java.text.MessageFormat;
/**
* Benchmark for method devirtualization and inlining.
*
* This is technically a microbenchmark (tested code is minimal), but
* we make a lot of effort to prevent "excessive" optimizations that
* would make results irrelevant or hard to analyse. The techniques
* are apparently very successfull for the current crop of JITs.
*
* (c) 2002 by Osvaldo Pinali Doederlein.
* Released to public domain.
*/
abstract public class MethodBench
{
/**
* Start time for the benchmark cycle.
*/
private static long start;
/**
* Total time for the benchmark cycle.
*/
private static long span;
/**
* Divider for the benchmark cycle, used for timer tuning.
*/
private static int divider;
/**
* Formatter for timings.
*/
private static final DecimalFormat fmt = new DecimalFormat("00.000");
/**
* Declare the helper here, init later, to fight dataflow optimizations.
*/
protected static HelperC helper;
/**
* Consumes a value produced by the benchmark, so its calculation cannot be
* eliminated as dead code (but it might still be computed in compilation time).
*/
protected static void consume (int value)
{
System.out.print(MessageFormat.format("", new Object[]{new Integer(value)}));
}
/**
* Starts one test.
*/
protected static void startBench (String header)
{
System.out.print(header);
helper = new HelperC();
start = System.currentTimeMillis();
divider = 1;
}
/**
* Checks if the benchmark can stop (enough precision obtained).
*/
protected static boolean checkEnd ()
{
span = System.currentTimeMillis() - start;
if (span >= 1000)
return true;
else
{
++divider;
return false;
}
}
/**
* Ends one test.
*/
protected static void endBench ()
{
consume(Helper.x);
System.out.print(fmt.format(span / 100.0 / divider));
}
}
--- HelperD.java
/**
* Used only to override the polymorphic method.
*/
public class HelperD extends HelperC implements HelperInterface
{
/**
* Makes Helper.polyHardF() even more polymorphic.
*/
public void polyHardF (int value) { x ^= value; }
}
--- Helper.java
/**
* Invoked methods are in a different class, to make optimizations
* harder (compilers may special-case for "local" calls).
* Method bodies are minimal because we are only interested in the call.
*/
public class Helper
{
/**
* Holds computed data, with non-optimizable initial value.
*/
public static int x = Integer.parseInt("0");
/**
* The polymorphic virtual method (Hard).
*/
public void polyHardF (int value) { x += value; }
/**
* The virtual method (Hard).
*/
public void virtualHardF (int value) { x += value; }
/**
* The non-virtual method (Hard).
*/
public final void finalHardF (int value) { x += value; }
/**
* The static method (Hard).
*/
public static void staticHardF (int value) { x += value; }
/**
* The polymorphic virtual method (Easy).
*/
public void polyEasyF (int value) { x++; }
/**
* The virtual method (Easy).
*/
public void virtualEasyF (int value) { x++; }
/**
* The non-virtual method (Easy).
*/
public final void finalEasyF (int value) { x++; }
/**
* The static method (Easy).
*/
public static void staticEasyF (int value) { x++; }
}
--- HelperInterface.java
/**
* Enables the interface test.
*/
public interface HelperInterface
{
/**
* Makes polyHardF() interface-callable.
*/
void polyHardF (int value);
}
--- HelperC.java
/**
* Used only to override the polymorphic method.
*/
public class HelperC extends HelperA
{
/**
* Makes Helper.polyHardF() even more polymorphic.
*/
public void polyHardF (int value) { x |= value; }
}
--- HelperB.java
/**
* Used only to override the polymorphic method.
*/
public class HelperB extends Helper implements HelperInterface
{
/**
* Makes Helper.polyHardF() even more polymorphic.
*/
public void polyHardF (int value) { x &= value; }
}
--- HelperA.java
/**
* Used only to override the polymorphic method.
*/
public class HelperA extends Helper
{
/**
* Makes Helper.polyHardF() polymorphic.
*/
public void polyHardF (int value) { x -= value; }
/**
* Makes Helper.polyEasyF() polymorphic.
*/
public void polyEasyF (int value) { x--; }
}
--- MethodHard.java
/**
* "Hard" test: Uses values not compilt-time computable for loop bounds, making
* things harder for loop optimizations (favors profile-driven compilers).
*
* (c) 2002 by Osvaldo Pinali Doederlein.
* Released to public domain.
*/
public class MethodHard extends MethodBench
{
/**
* Declare the benchmark instance here, init later, to fight dataflow
optimizations.
*/
static MethodHard t;
/**
* Optimizer-friendly constant for the loop's max bound.
*/
static final int CALLS = Integer.parseInt("100000000");
/**
* Optimizer-friendly constant for the loops' lower bounds.
*/
static final int ZERO = Integer.parseInt("0");
/**
* Optimizer-friendly constant for the benchmark controller's loop.
*/
static final int CYCLES = Integer.parseInt("5");
/**
* Tests interface method.
*/
final void benchInterface ()
{
int calls = CALLS / 1000;
HelperInterface helper = null, h1 = new HelperB(), h2 = new HelperD();
for (int i = 0; i < 1000; ++i)
{
switch (i % 500)
{
case 0: helper = h1; break;
case 1: helper = h2; break;
}
for (int j = ZERO; j < calls; ++j)
helper.polyHardF(i);
}
}
/**
* Tests "truly" polymorphic virtual method.
*/
final void benchTrulyPoly ()
{
int calls = CALLS / 1000;
Helper helper = null, h1 = new Helper(), h2 = new HelperA();
Helper h3 = new HelperB(), h4 = new HelperC(), h5 = new HelperD();
for (int i = 0; i < 1000; ++i)
{
switch (i % 200)
{
case 0: helper = h1; break;
case 1: helper = h2; break;
case 2: helper = h3; break;
case 3: helper = h4; break;
case 4: helper = h5; break;
}
for (int j = ZERO; j < calls; ++j)
helper.polyHardF(i);
}
}
/**
* Tests polymorphic virtual method.
*/
final void benchPoly ()
{
for (int i = ZERO; i < CALLS; ++i)
helper.polyHardF(i);
}
/**
* Tests virtual method.
*/
final void benchVirtual ()
{
for (int i = ZERO; i < CALLS; ++i)
helper.virtualHardF(i);
}
/**
* Tests non-virtual method.
*/
final void benchFinal ()
{
for (int i = ZERO; i < CALLS; ++i)
helper.finalHardF(i);
}
/**
* Tests static method.
*/
final void benchStatic ()
{
for (int i = ZERO; i < CALLS; ++i)
Helper.staticHardF(i);
}
/**
* Benchmark startup.
*/
public static void main (String[] args)
{
System.out.println("*** Testing (Hard) ***");
for (int i = ZERO; i < CYCLES; ++i)
bench();
}
/**
* Benchmark controller for "Hard" tests.
*/
static void bench ()
{
t = new MethodHard();
new HelperD().polyHardF(1);
consume(Helper.x);
startBench("Interface: ");
do { t.benchInterface(); } while (!checkEnd());
endBench();
startBench(" TrulyPoly: ");
do { t.benchTrulyPoly(); } while (!checkEnd());
endBench();
startBench(" Poly: ");
do { t.benchPoly(); } while (!checkEnd());
endBench();
startBench(" Virtual: ");
do { t.benchVirtual(); } while (!checkEnd());
endBench();
startBench(" Final: ");
do { t.benchFinal(); } while (!checkEnd());
endBench();
startBench(" Static: ");
do { t.benchStatic(); } while (!checkEnd());
endBench();
System.out.println();
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
Use older VMs, then losing important performance and API
enhancements of JDK 1.4.x.
This perf bug is important because in real world OO code,
there are lots of interface calls and virtual calls that are
really polymorphic and cannot be optimized by HotSpot's
devirtualization tricks. In these cases, HotSpot should be
smart enough to not attempt any optimization and be happy
with the standard dynamic dispatch code and no inlining.
(Review ID: 179170)
======================================================================
Name: jl125535 Date: 01/14/2003
FULL PRODUCT VERSION :
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]
A DESCRIPTION OF THE PROBLEM :
I designed the MethodBench benchmark to measure how
effectively Java VMs optimize method invocations, with a
focus on devirtualization and inlining. The first version
of the benchmark was published here:
http://javalobby.org/members/jpr/methodopt.jsp and the
results are outrageously good for Sun JDK 1.4.1's HotSpot
VMs. My motivation is that existing syntethic benchmarks of
this kind (e.g. JGF's) are obsoleted by current optimizers;
MethodBench applies every technique I know to prevent the
"wrong" optimizations from invalidating the benchmark, and
uses multiple variations of the tests to analyse the
optimizer's behavior in all important scenarios (see
article; this version contains a few additional tricks). (I
have yet to fix my use of Math.random() but it's just a
minor issue.)
Updating the benchmark to contemplate harder scenarios --
call sites that cannot be devirtualized, and interface calls
-- the initial scores reveal severely bad performance in the
latest HotSpot VMs, that consistently produce results up to
5X slower that other compilers (including Sun's but also
IBM's, one static compiler, and two .NET implementations).
It seems that HotSpot is desperately trying to apply
aggressive optimizations that cannot deliver any benefit in
the new, worst-case call sites, with the results below. Look
at "Polymorphic", "TrulyPoly" and "Poly" scores; all these
exhibit variable degrees of degenerated performance (i.e.,
substantially worse than older Sun VMs) for HotSpot 1.4.0
(Server) and HotSpot 1.4.1 (both Client and Server).
HotSpot Client 1.3.1_06:
*** Testing (Hard) ***
Interface: 15,160 TrulyPoly: 13,120 Poly: 11,720 Virtual:
11,720 Final: 05,310 Static: 03,960
Interface: 14,680 TrulyPoly: 12,810 Poly: 11,870 Virtual:
11,570 Final: 08,670 Static: 03,853
Interface: 35,780 TrulyPoly: 12,810 Poly: 12,030 Virtual:
11,720 Final: 05,235 Static: 03,853
Interface: 14,530 TrulyPoly: 12,810 Poly: 12,190 Virtual:
12,190 Final: 05,155 Static: 03,853
Interface: 14,380 TrulyPoly: 12,970 Poly: 12,180 Virtual:
12,030 Final: 05,160 Static: 03,853
*** Testing (Easy) ***
Interface: 11,880 TrulyPoly: 13,120 Poly: 11,880 Virtual:
11,870 Final: 05,235 Static: 04,427
Interface: 11,560 TrulyPoly: 12,820 Poly: 11,870 Virtual:
11,880 Final: 05,230 Static: 03,857
Interface: 12,030 TrulyPoly: 12,960 Poly: 11,880 Virtual:
12,030 Final: 05,390 Static: 03,853
Interface: 14,530 TrulyPoly: 12,970 Poly: 12,030 Virtual:
12,190 Final: 05,235 Static: 03,853
Interface: 14,220 TrulyPoly: 12,970 Poly: 12,030 Virtual:
12,030 Final: 05,235 Static: 03,800
HotSpot Server 1.3.1_06:
*** Testing (Hard) ***
Interface: 14,220 TrulyPoly: 10,620 Poly: 09,065 Virtual:
00,500 Final: 00,491 Static: 00,357
Interface: 13,750 TrulyPoly: 10,310 Poly: 08,985 Virtual:
00,370 Final: 00,376 Static: 00,357
Interface: 12,970 TrulyPoly: 10,470 Poly: 09,840 Virtual:
00,376 Final: 00,385 Static: 00,350
Interface: 12,960 TrulyPoly: 10,630 Poly: 08,905 Virtual:
00,430 Final: 00,430 Static: 00,423
Interface: 13,130 TrulyPoly: 10,460 Poly: 08,910 Virtual:
00,441 Final: 00,430 Static: 00,435
*** Testing (Easy) ***
Interface: 10,470 TrulyPoly: 00,391 Poly: 00,323 Virtual:
00,217 Final: 00,208 Static: 00,161
Interface: 11,560 TrulyPoly: 00,267 Poly: 00,267 Virtual:
00,159 Final: 00,159 Static: 00,164
Interface: 08,985 TrulyPoly: 00,238 Poly: 00,244 Virtual:
00,156 Final: 00,161 Static: 00,161
Interface: 13,430 TrulyPoly: 00,242 Poly: 00,238 Virtual:
00,161 Final: 00,159 Static: 00,161
Interface: 12,970 TrulyPoly: 00,242 Poly: 00,242 Virtual:
00,159 Final: 00,159 Static: 00,161
HotSpot Client 1.4.0_03:
*** Testing (Hard) ***
Interface: 14,850 TrulyPoly: 12,970 Poly: 11,720 Virtual:
05,155 Final: 05,155 Static: 02,695
Interface: 14,690 TrulyPoly: 12,970 Poly: 11,870 Virtual:
05,155 Final: 05,160 Static: 02,615
Interface: 14,380 TrulyPoly: 12,970 Poly: 12,030 Virtual:
05,155 Final: 05,080 Static: 02,655
Interface: 14,380 TrulyPoly: 13,120 Poly: 12,030 Virtual:
05,080 Final: 05,155 Static: 02,578
Interface: 14,530 TrulyPoly: 13,130 Poly: 11,870 Virtual:
05,155 Final: 05,155 Static: 02,618
*** Testing (Easy) ***
Interface: 11,880 TrulyPoly: 04,427 Poly: 05,465 Virtual:
05,550 Final: 05,235 Static: 03,800
Interface: 12,810 TrulyPoly: 04,167 Poly: 05,390 Virtual:
05,315 Final: 05,310 Static: 03,853
Interface: 11,720 TrulyPoly: 04,167 Poly: 05,235 Virtual:
05,310 Final: 05,315 Static: 03,853
Interface: 11,870 TrulyPoly: 04,167 Poly: 05,235 Virtual:
05,390 Final: 05,315 Static: 03,800
Interface: 15,310 TrulyPoly: 04,167 Poly: 05,315 Virtual:
05,390 Final: 05,310 Static: 03,857
HotSpot Server 1.4.0_03:
*** Testing (Hard) ***
Interface: 30,150 TrulyPoly: 30,630 Poly: 00,634 Virtual:
00,350 Final: 00,363 Static: 00,350
Interface: 29,060 TrulyPoly: 30,940 Poly: 00,598 Virtual:
00,357 Final: 00,350 Static: 00,357
Interface: 27,970 TrulyPoly: 29,060 Poly: 00,588 Virtual:
00,350 Final: 00,350 Static: 00,357
Interface: 28,910 TrulyPoly: 29,060 Poly: 00,588 Virtual:
00,350 Final: 00,357 Static: 00,345
Interface: 28,910 TrulyPoly: 29,060 Poly: 00,606 Virtual:
00,345 Final: 00,357 Static: 00,345
*** Testing (Easy) ***
Interface: 13,830 TrulyPoly: 00,132 Poly: 00,147 Virtual:
00,128 Final: 00,127 Static: 00,128
Interface: 24,210 TrulyPoly: 00,125 Poly: 00,164 Virtual:
00,125 Final: 00,127 Static: 00,125
Interface: 24,530 TrulyPoly: 00,125 Poly: 00,164 Virtual:
00,128 Final: 00,125 Static: 00,128
Interface: 24,530 TrulyPoly: 00,127 Poly: 00,161 Virtual:
00,127 Final: 00,127 Static: 00,127
Interface: 24,530 TrulyPoly: 00,127 Poly: 00,164 Virtual:
00,125 Final: 00,127 Static: 00,125
HotSpot Client 1.4.1_01:
*** Testing (Hard) ***
Interface: 47,970 TrulyPoly: 40,160 Poly: 35,780 Virtual:
03,903 Final: 03,960 Static: 04,530
Interface: 47,810 TrulyPoly: 40,630 Poly: 35,930 Virtual:
03,853 Final: 03,907 Static: 05,080
Interface: 48,750 TrulyPoly: 39,840 Poly: 35,930 Virtual:
03,857 Final: 03,853 Static: 05,155
Interface: 48,590 TrulyPoly: 39,840 Poly: 35,780 Virtual:
03,907 Final: 03,853 Static: 05,390
Interface: 48,590 TrulyPoly: 40,000 Poly: 35,940 Virtual:
03,853 Final: 03,853 Static: 05,000
*** Testing (Easy) ***
Interface: 39,380 TrulyPoly: 04,273 Poly: 05,230 Virtual:
05,160 Final: 05,075 Static: 03,853
Interface: 39,380 TrulyPoly: 03,907 Poly: 05,075 Virtual:
05,155 Final: 05,160 Static: 03,853
Interface: 58,750 TrulyPoly: 03,903 Poly: 05,080 Virtual:
05,155 Final: 05,080 Static: 03,853
Interface: 58,900 TrulyPoly: 03,857 Poly: 05,155 Virtual:
05,075 Final: 05,160 Static: 03,853
Interface: 57,970 TrulyPoly: 03,957 Poly: 05,155 Virtual:
05,080 Final: 05,155 Static: 03,853
HotSpot Server 1.4.1_01:
*** Testing (Hard) ***
Interface: 46,720 TrulyPoly: 47,960 Poly: 01,111 Virtual:
00,350 Final: 00,363 Static: 00,357
Interface: 47,490 TrulyPoly: 47,810 Poly: 01,063 Virtual:
00,350 Final: 00,350 Static: 00,350
Interface: 47,650 TrulyPoly: 47,660 Poly: 01,046 Virtual:
00,357 Final: 00,356 Static: 00,350
Interface: 47,340 TrulyPoly: 47,660 Poly: 01,032 Virtual:
00,357 Final: 00,350 Static: 00,357
Interface: 47,970 TrulyPoly: 47,500 Poly: 01,046 Virtual:
00,356 Final: 00,350 Static: 00,357
*** Testing (Easy) ***
Interface: 18,907 TrulyPoly: 00,196 Poly: 00,196 Virtual:
00,127 Final: 00,128 Static: 00,125
Interface: 51,400 TrulyPoly: 00,189 Poly: 00,192 Virtual:
00,127 Final: 00,123 Static: 00,123
Interface: 55,150 TrulyPoly: 00,189 Poly: 00,192 Virtual:
00,127 Final: 00,125 Static: 00,125
Interface: 55,150 TrulyPoly: 00,189 Poly: 00,192 Virtual:
00,128 Final: 00,123 Static: 00,127
Interface: 55,160 TrulyPoly: 00,189 Poly: 00,192 Virtual:
00,125 Final: 00,123 Static: 00,127
IBM JDK 1.3.1 (20020821):
*** Testing (Hard) ***
Interface: 09,300 TrulyPoly: 09,065 Poly: 10,310 Virtual:
02,540 Final: 01,308 Static: 01,270
Interface: 09,060 TrulyPoly: 08,985 Poly: 10,470 Virtual:
02,312 Final: 01,328 Static: 01,270
Interface: 09,140 TrulyPoly: 09,060 Poly: 10,320 Virtual:
02,406 Final: 01,329 Static: 01,289
Interface: 09,060 TrulyPoly: 08,985 Poly: 10,310 Virtual:
02,500 Final: 01,328 Static: 01,270
Interface: 09,060 TrulyPoly: 09,065 Poly: 10,310 Virtual:
02,468 Final: 01,429 Static: 01,289
*** Testing (Easy) ***
Interface: 09,145 TrulyPoly: 02,280 Poly: 02,406 Virtual:
02,344 Final: 00,005 Static: 00,000
Interface: 09,375 TrulyPoly: 02,374 Poly: 02,500 Virtual:
02,126 Final: 00,000 Static: 00,000
Interface: 09,140 TrulyPoly: 02,438 Poly: 02,436 Virtual:
02,000 Final: 00,000 Static: 00,000
Interface: 09,140 TrulyPoly: 02,188 Poly: 02,540 Virtual:
02,280 Final: 00,000 Static: 00,000
Interface: 09,215 TrulyPoly: 02,250 Poly: 02,282 Virtual:
02,188 Final: 00,000 Static: 00,000
Excelsior JET 3.0:
*** Testing (Hard) ***
Interface: 10,940 TrulyPoly: 10,310 Poly: 11,560 Virtual:
11,560 Final: 01,047 Static: 01,016
Interface: 11,250 TrulyPoly: 10,310 Poly: 11,400 Virtual:
11,570 Final: 01,146 Static: 01,047
Interface: 11,400 TrulyPoly: 10,470 Poly: 11,560 Virtual:
11,720 Final: 01,063 Static: 01,015
Interface: 11,410 TrulyPoly: 10,310 Poly: 11,560 Virtual:
11,560 Final: 01,063 Static: 01,062
Interface: 11,100 TrulyPoly: 10,310 Poly: 11,400 Virtual:
11,560 Final: 01,000 Static: 01,146
*** Testing (Easy) ***
Interface: 10,940 TrulyPoly: 10,940 Poly: 10,930 Virtual:
10,780 Final: 00,645 Static: 00,644
Interface: 10,940 TrulyPoly: 10,930 Poly: 10,780 Virtual:
10,940 Final: 00,644 Static: 00,635
Interface: 10,940 TrulyPoly: 11,090 Poly: 10,780 Virtual:
10,940 Final: 00,634 Static: 00,644
Interface: 11,100 TrulyPoly: 10,930 Poly: 10,940 Virtual:
10,940 Final: 00,635 Static: 00,644
Interface: 10,780 TrulyPoly: 11,090 Poly: 10,940 Virtual:
10,780 Final: 00,644 Static: 00,644
Microsoft .NET 1.1beta:
*** Testing (Hard) ***
Interface: 10,150 TrulyPoly: 08,980 Poly: 10,310 Virtual:
10,460 Final: 03,853 Static: 03,123
Interface: 10,150 TrulyPoly: 08,980 Poly: 10,310 Virtual:
10,310 Final: 03,853 Static: 03,045
Interface: 10,310 TrulyPoly: 08,980 Poly: 10,310 Virtual:
10,150 Final: 03,853 Static: 03,123
Interface: 10,310 TrulyPoly: 08,905 Poly: 10,310 Virtual:
10,460 Final: 03,853 Static: 03,593
Interface: 10,150 TrulyPoly: 09,060 Poly: 10,310 Virtual:
10,620 Final: 03,853 Static: 03,203
*** Testing (Easy) ***
Interface: 10,310 TrulyPoly: 08,980 Poly: 10,310 Virtual:
10,310 Final: 03,853 Static: 05,700
Interface: 10,310 TrulyPoly: 08,905 Poly: 10,310 Virtual:
10,310 Final: 03,853 Static: 05,545
Interface: 10,310 TrulyPoly: 08,980 Poly: 10,460 Virtual:
10,620 Final: 03,853 Static: 05,230
Interface: 10,150 TrulyPoly: 08,980 Poly: 10,310 Virtual:
10,460 Final: 03,853 Static: 05,545
Interface: 10,150 TrulyPoly: 08,980 Poly: 10,310 Virtual:
10,310 Final: 03,800 Static: 05,620
Mono 0.17:
*** Testing (Hard) ***
Interface: 14,84 TrulyPoly: 13,91 Poly: 14,69 Virtual:
15,15 Final: 3,96 Static: 5,075
Interface: 14,22 TrulyPoly: 13,59 Poly: 15 Virtual: 14,69
Final: 3,95666666666667 Static: 5,47
Interface: 14,38 TrulyPoly: 13,43 Poly: 15,16 Virtual:
14,84 Final: 4,06333333333333 Static: 6,25
Interface: 14,06 TrulyPoly: 13,59 Poly: 14,85 Virtual: 15
Final: 3,90333333333333 Static: 5,16
Interface: 14,53 TrulyPoly: 13,43 Poly: 14,85 Virtual:
14,37 Final: 4,11333333333333 Static: 5,705
*** Testing (Easy) ***
Interface: 13,59 TrulyPoly: 15,78 Poly: 17,66 Virtual:
17,5 Final: 13,12 Static: 12,35
Interface: 13,28 TrulyPoly: 15,93 Poly: 17,5 Virtual:
17,66 Final: 13,12 Static: 11,88
Interface: 13,43 TrulyPoly: 16,41 Poly: 17,5 Virtual:
17,34 Final: 13,75 Static: 12,19
Interface: 13,28 TrulyPoly: 15,93 Poly: 17,5 Virtual:
17,81 Final: 13,6 Static: 12,18
Interface: 13,13 TrulyPoly: 16,25 Poly: 17,18 Virtual:
17,82 Final: 13,43 Static: 11,88
REGRESSION. Last worked in version 1.3
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. javac *.java
2. java [-server] -Xbatch MethodEasy
3. java [-server] -Xbatch MethodHard
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
(Several public classes, save to proper individual .java files)
(Ask me if you want the full sources and scripts, but this is
enough for the Java platform tests)
--- MethodEasy.java
/**
* "Easy" test: Uses only compile-time constants for loop bounds, making
* things easier for loop optimizations reliant on static analysis.
*
* (c) 2002 by Osvaldo Pinali Doederlein.
* Released to public domain.
*/
public class MethodEasy extends MethodBench
{
/**
* Declare the benchmark instance here, init later, to fight dataflow
optimizations.
*/
static MethodEasy t;
/**
* Optimizer-friendly constant for the loop's max bound.
*/
static final int CALLS = 100000000;
/**
* Optimizer-friendly constant for the loops' lower bounds.
*/
static final int ZERO = 0;
/**
* Optimizer-friendly constant for the benchmark controller's loop.
*/
static final int CYCLES = 5;
/**
* Tests interface method.
*/
final void benchInterface ()
{
HelperInterface helper = (Math.random() < 0.5) ?
(HelperInterface)new HelperB() : (HelperInterface)new HelperD();
for (int i = ZERO; i < CALLS; ++i)
helper.polyHardF(i);
}
/**
* Tests "truly" polymorphic virtual method.
*/
final void benchTrulyPoly ()
{
final int calls = CALLS / 1000;
HelperC helper = null, h1 = new HelperC(), h2 = new HelperD();
for (int i = 0; i < 1000; ++i)
{
switch (i % 500)
{
case 0: helper = h1; break;
case 1: helper = h2; break;
}
for (int j = ZERO; j < calls; ++j)
helper.polyEasyF(i);
}
}
/**
* Tests polymorphic virtual method.
*/
final void benchPoly ()
{
for (int i = ZERO; i < CALLS; ++i)
helper.polyEasyF(i);
}
/**
* Tests virtual method.
*/
final void benchVirtual ()
{
for (int i = ZERO; i < CALLS; ++i)
helper.virtualEasyF(i);
}
/**
* Tests non-virtual method.
*/
final void benchFinal ()
{
for (int i = ZERO; i < CALLS; ++i)
helper.finalEasyF(i);
}
/**
* Tests static method.
*/
final void benchStatic ()
{
for (int i = ZERO; i < CALLS; ++i)
Helper.staticEasyF(i);
}
/**
* Benchmark startup.
*/
public static void main (String[] args)
{
System.out.print