JDK-6533165 : Failure to optimize methods that unconditionally throw
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 7,9,10
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2007-03-10
  • Updated: 2018-12-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Relates :  
Description
While trying to improve ArrayList performance for

5103956: (coll) Suggested improvement to speed up ArrayList<E> get and set calls

I encountered an anomaly in server compiler optimization.

Basically, since the performance of ArrayList.get() and set() is critical, 
we were willing to perform code micro-tweaks to make hotspot optimizers happy.

In particular, for error-handling, we had ArrayList.rangeCheck:

    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
    }

We refactored this to make the client compiler happier.

All of the possible refactorings gave equal performance under the server compiler,
except one.  Here are 3 refactorings:
 
       if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
 
    private String outOfBoundsMsg(int index) {
	return "Index: "+index+", Size: "+size;
    }
 

----------

          if (index >= size)
            throw outOfBoundsException(index);
 
    private IndexOutOfBoundsException outOfBoundsException(int index) {
	return new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
    }

----------

        if (index >= size)
            outOfBounds(index);
 
    private void outOfBounds(int index) {
	throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
    }

----------

The refactoring using outOfBounds is dramatically slower on my microbenchmark
than the others.  Using j2se/test/java/util/ArrayList/RangeCheckMicroBenchmark.java
I get, e.g. on solaris-amd64:

==> javac -Xlint:all RangeCheckMicroBenchmark.java
==> java -server -esa -ea RangeCheckMicroBenchmark
Method            Millis Ratio
get                   53 1.000
set                   48 0.907
get/set              188 3.487
add/remove at end   1360 25.210

vs.

==> javac -Xlint:all RangeCheckMicroBenchmark.java
==> java -server -esa -ea RangeCheckMicroBenchmark
Method            Millis Ratio
get                  180 1.000
set                  363 2.006
get/set              514 2.844
add/remove at end   1227 6.784

Notice the up-to-factor-of-8 decrease in performance.  A big penalty for
just moving some code around.

I'm not a hotspot engineer, but it looks like methods that unconditionally
throw confuse the optimizer.  But such methods are typical of attempts to
move error handling into a separate method, and is effective at speeding
up the client compiler, so users are likely to do this sort of thing.
The server compiler needs to examine outOfBounds and understand that it throws, 
but not inline it.  Maybe.