ClassValue perf?
Peter Levart
peter.levart at gmail.com
Sat May 2 22:32:45 UTC 2015
Hi,
I have considered using ClassValue in the past because it is quite fast
(as fast as a hash table can be) but was afraid of footprint overhead,
because I saw with debugger a structure being grown before my eyes that
was quite complicated and that I could not understand entirely. Now I
took some time to actually try to understand and measure it. In a
typical scenario ClassValue was designed for (initial capacity == 32),
initializing for example 16 ClassValues x 1024 Classes, jmap shows the
following interesting entries which all amount to overhead (that's on
64bit JVM with compressed OOPS):
num #instances #bytes class name
----------------------------------------------
1: 16384 655360 java.util.WeakHashMap$Entry
2: 16402 524864 java.lang.ClassValue$Entry
8: 1024 147456 [Ljava.util.WeakHashMap$Entry;
9: 1025 147480 [Ljava.lang.ClassValue$Entry;
13: 1024 65536 java.lang.ClassValue$ClassValueMap
17: 1024 32768 java.lang.ref.ReferenceQueue
21: 1024 16384 java.lang.ref.ReferenceQueue$Lock
----------------------------------------------
Total: 1589848 (97 bytes/entry)
ClassValueMap is a WeakHashMap subclass which contains an array of
WeakHashMap$Entry objects. In addition it maintains a parallel "cache"
array of ClassValue$Entry objects. Both of those entry objects are
WeakReferences. It means that each (Class,ClassValue) pair needs 2
WeakReferences (with additional fields) and 2 array slots to hold
associated value.
So I wondered, would it be possible to simplify CV and make it more
straight-forward by taking away almost half of overhead to get this:
num #instances #bytes class name
----------------------------------------------
1: 16384 655360 java.lang.ClassValue$Entry
7: 1024 147456 [Ljava.lang.ClassValue$Entry;
13: 1024 40960 java.lang.ClassValue$ClassValueMap
15: 1024 32768 java.lang.ref.ReferenceQueue
19: 1024 16384 java.lang.ref.ReferenceQueue$Lock
----------------------------------------------
Total: 892928 (54 bytes/entry)
I tried and came up with the following:
http://cr.openjdk.java.net/~plevart/misc/ClassValue.Alternative/webrev.01/
It was not easy to keep the performance approximately on the same level
while re-designing the implementation. But I think I managed to get it
to perform mostly the same for the fast-path case. This alternative
implementation also guarantees that, unless remove() is used,
computeValue() is called exactly once per (Class, ClassValue) pair.
Original implementation explains that it can redundantly compute more
than one value and then throw away all but one. This alternative
implementation could easily be modified to do the same (using CAS
instead of lock) if anyone is afraid of deadlocks.
Here's a micro benchmark with results measuring original vs. alternative
implementation. Attached results are for JDK9 on Intel i7 / Linux box
using 4 concurrent threads for tests:
http://cr.openjdk.java.net/~plevart/misc/ClassValue.Alternative/ClassValueBench.java
It would be interesting to see if and how it works for you too (just
compile and prepend to bootclasspath).
Regards, Peter
On 04/30/2015 03:57 PM, Michael Haupt wrote:
> Hi,
>
> I'm looking at JDK-8031043 and would appreciate if you guys could send
> any code you think might benefit from a smaller initial CV memory
> footprint my way. Given what I've read, it could have some impact
> during startup (Groovy?) if the value is reduced to 1.
>
> Best,
>
> Michael
>
>> Am 30.04.2015 um 15:43 schrieb Charles Oliver Nutter
>> <headius at headius.com <mailto:headius at headius.com>>:
>>
>> On Mon, Apr 27, 2015 at 12:50 PM, Jochen Theodorou <blackdrag at gmx.org
>> <mailto:blackdrag at gmx.org>> wrote:
>>> Am 27.04.2015 19:17, schrieb Charles Oliver Nutter:
>>>> Jochen: Is your class-to-metaclass map usable apart from the Groovy
>>>> codebase?
>>>
>>>
>>> Yes. Look for
>>> org.codehaus.groovy.reflection.GroovyClassValuePreJava7 which
>>> is normally wrapped by a factory.
>>
>> Excellent, thank you!
>>
>> - Charlie
>
>
> --
>
> Oracle <http://www.oracle.com/>
> Dr. Michael Haupt | Principal Member of Technical Staff
> Phone: +49 331 200 7277 | Fax: +49 331 200 7561
> OracleJava Platform Group | HotSpot Compiler Team
> Oracle Deutschland B.V. & Co. KG, Schiffbauergasse 14 | 14467 Potsdam,
> Germany
> Green Oracle <http://www.oracle.com/commitment> Oracle is committed
> to developing practices and products that help protect the environment
>
>
>
>
> _______________________________________________
> mlvm-dev mailing list
> mlvm-dev at openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/mlvm-dev/attachments/20150503/25188b20/attachment.html>
More information about the mlvm-dev
mailing list