ClassValue perf?

Remi Forax forax at univ-mlv.fr
Sun May 3 09:10:42 UTC 2015


Hi Peter,
computeValue() may recursively call get() by example to crawle the 
inheritance hierarchy so i am not sure a lock is a good idea here 
because in that case, it usually takes several millis to complete the to 
level computeValue.

regards,
Rémi

On 05/03/2015 12:32 AM, Peter Levart wrote:
> 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
>
>
>
> _______________________________________________
> 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/f64e72c9/attachment-0001.html>


More information about the mlvm-dev mailing list