On 04/29/2016 10:28 AM, Michael Haupt wrote:

see http://cr.openjdk.java.net/~mhaupt/8031043/ <http://cr.openjdk.java.net/%7Emhaupt/8031043/> for a snapshot of what is currently available.

We have three patches:
* Christian's, which simply reduces the HashMap size,
* Peter's, which refactors ClassValueMap into a WeakHashMap,
* mine, which attempts to introduce the single-value storage optimisation John had suggested (I worked on performance with Aleksey - thanks!).

All of these are collected in the patches subdirectory for convenience. (Peter, I adapted your patch to the new Unsafe location.)

I extended Peter's benchmark (thanks!) to cover single-value storage; the source code is in the benchmark subdirectory, together with raw results from running the benchmark with each of the three patches applied. A results-only overview is in benchmark-results.txt.

The three are roughly on par. I'm not sure the single-value storage optimisation improves much on footprint given the additional data that must be kept around to make transition to map storage safe.


I must admit that my old patch is very complex, so I doubt anyone will take time to review it. It is almost a clean-room re-implementation of ClassValue API. My main motivation was footprint optimization for all sizes - not just one value per class as I doubt this will be very common situation anyway. Current ClassValue maintains 2 parallel hash-tables per class. A WeakHashMap which is accessed with proper synchronization and an optimized "cache" of entries for quick access. This makes it consume almost 100 bytes per (Class, ClassValue) pair. I managed to almost half the overhead for typical situation (1024 classes x 16 ClassValue(s)), but for the price of complexity.

Reviving this thread made me think about ClassValue again and I got another idea. This is an experiment to see if ConcurrentHashMap could be leveraged to implement ClassValue API with little added complexity:


And here are the results of a benchmark comparing JDK 9 original with this alternative:


It is a little slower for random access of bigger sizes and #s of classes. Most probably a consequence of reduced cache hit ratio as CHM is a classical hash table with buckets implemented as linked list of entries whereas jdk 9 ClassValue cache is a linear-scan hash table which has better cache locality. This is particularly obvious in sequential access where CHM behaves on-par. It's a pity that CHM has a non-changeable load factor of 0.75 as changing this to 0.5 would most certainly improve benchmark results for a little more memory.

Where this version excels is in footprint. I managed to more than half the overhead. There's only a single ReferenceQueue needed and consequently expunging of stale data is more prompt and thorough. The code of ClassValue has been more than halved too.

What do you think?

Regards, Peter




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 | LangTools Team | Nashorn
Oracle Deutschland B.V. & Co. KG | Schiffbauergasse 14 | 14467 Potsdam, Germany

ORACLE Deutschland B.V. & Co. KG | Hauptverwaltung: Riesstraße 25, D-80992 München
Registergericht: Amtsgericht München, HRA 95603

Komplementärin: ORACLE Deutschland Verwaltung B.V. | Hertogswetering 163/167, 3543 AS Utrecht, Niederlande
Handelsregister der Handelskammer Midden-Nederland, Nr. 30143697
Geschäftsführer: Alexander van der Ven, Jan Schultheiss, Val Maher
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 mailing list

Reply via email to