hg: jdk8/tl/jdk: 7194897: JSR 292: Cannot create more than 16 instances of an anonymous class; ...
Peter Levart
peter.levart at gmail.com
Thu Nov 7 08:36:14 UTC 2013
On 11/07/2013 02:20 AM, John Rose wrote:
> On Nov 6, 2013, at 11:30 AM, Peter Levart <peter.levart at gmail.com
> <mailto:peter.levart at gmail.com>> wrote:
>
>> Well, indexOf(char) or lastIndexOf(char) searches for a single char.
>> We can do better searching backwards for two chars at the same time.
>>
>> If the "name" of VM-anonymous class is always ending with pattern:
>> "slash followed by some decimal digits" then the following would be
>> even faster:
>
> Although this reasoning is plausible, it is not a reliable conclusion,
> and should not drive edits of Java code without careful measurement.
> The reasoning assumes a performance model based on the interpreter
> and bytecode count. But performance depends on native code produced
> by the JIT.
I agree. I should have measured it...
>
> An optimizing JIT will usually transform the code deeply. For string
> scanning, for example, HotSpot has an intrinsic for
> String.indexOf(String) that uses totally different code from a
> user-coded loop. (It is not currently so for String.indexOf(int), but
> String.indexOf("/") is potentially very fast.)
>
> Also, with your example code, the combined loop may often be faster
> than two back-to-back loops, but simpler loops can sometimes be
> vectorized more robustly, to the point where back-to-back simple
> loops, if vectorized, may be competitive with a hand-fused loop.
>
> So loop complexity and method intrinsics can create surprises for
> those who rely on simple performance modesl
>
> Some day we will get to a world where loops are specified stream-wise,
> and robustly optimized without this sort of manual intervention. In
> the mean time, be careful about advising hand-optimizations of Java
> code. They can backfire, by confusing the JIT and preventing
> optimizations that would apply to simpler code.
>
> — John
So I did measure it. I took two classes with the following names:
com.test.pkg.PerfTest$Classic$1
com.test.pkg.PerfTest$$Lambda$1/925858445
Typically package names will be even relatively longer than in this example.
I measured the following implementations:
public static boolean isVMAnonymousClass(Class<?> cls) {
return cls.getSimpleName().contains("/");
}
public static boolean isVMAnonymousClass_FAST1(Class<?> cls) {
String name = cls.getName();
for (int i = name.length() - 1; i >= 0; i--) {
char c = name.charAt(i);
if (c == '.') return false;
if (c == '/') return true;
}
return false;
}
public static boolean isVMAnonymousClass_FAST2(Class<?> cls) {
String name = cls.getName();
for (int i = name.length() - 1; i >= 0; i--) {
char c = name.charAt(i);
if (c == '/') return true;
if (c < '0' || c > '9') return false;
}
return false;
}
public static boolean isVMAnonymousClass_indexOf(Class<?> cls) {
return cls.getName().indexOf("/") > -1;
}
I also tried String.lastIndexOf(String) and it is a little faster for
true return, since it only scans backwards until the "/" is found, but
it is slower than String.indexOf(String) for "false" return. Is it not
intrinsified?
Here are the results:
http://cr.openjdk.java.net/~plevart/jdk8-tl/isVmAnonymousClass/results.txt
I think that any of the above implementations that doesn't use
Class.getSimpleName() is good. The FAST2 variant is favourable for false
return since it typically decides after examining a single character at
end of class name and is still among the fastest for true return...
Here's the code I used for testing:
http://cr.openjdk.java.net/~plevart/jdk8-tl/isVmAnonymousClass/com/test/pkg/PerfTest.java
http://cr.openjdk.java.net/~plevart/jdk8-tl/isVmAnonymousClass/si/pele/microbench/TestRunner.java
Regards, Peter
More information about the core-libs-dev
mailing list