Hi Michael,

On 05/06/2016 04:48 PM, Michael Haupt wrote:
Hi Peter,

thank you. I've run the full benchmark in my setup and uploaded the updated cumulative results to http://cr.openjdk.java.net/~mhaupt/8031043/ <http://cr.openjdk.java.net/%7Emhaupt/8031043/>.

The benchmark indeed shows that this latest addition to the group slows down random and sequential access, especially for small numbers of values and classes. The OpenJDK tests are fine; I'm running a batch of internal tests as well.

Given that one concern with this issue, next to reducing footprint, was to optimise for the single-value case, I'm still a bit hesitant even though the sheer amount of code reduction is impressive. I'll evaluate further.

Interesting. I observed quite the opposite on my machine (i7-4771, 8 MiB cache) . For sequential access pattern or for random access with small number of CV(s) and Class(es) the results are comparable. Only for 256 CV(s) x 1024 Class(es) and with random access pattern, I observed about 20% drop of performance which I attributed to the difference in design of CHM vs. the 'cache' of JDK 9 ClassValue (worse CPU cache locality for CHM):

http://cr.openjdk.java.net/~plevart/misc/ClassValue.Alternative2/ClassValueBench.java

I doubt that single value per Class instance is something that is beneficial to optimize. Such optimization would be very fragile so it would not be something to rely on. Typical or even worst case performance is more important in my opinion.

The fast-path lookup performance is the most important performance aspect of ClassValue, but it is not the only one that can be observed. Footprint and consequential GC / expunging overhead is also something to consider. The implementation presented in my webrev.02 maintains a linked list of weakly-referenced ClassValueMap(s). For each stale dequeued key, it probes each map and removes such key from any live map(s) containing it. This works optimally when the matrix of (ClassValue, Class) pairs is not sparse. I did an experiment with alternative expunging design where I maintain an array of weakly-referenced ClassValueMap(s) on each key that is inserted in them. This has approx. 10% additiona footprint overhead compared to original expunging design (but still just half the footprint overhead of jdk 9 ClassValue design):

http://cr.openjdk.java.net/~plevart/misc/ClassValue.Alternative2/webrev.03/

The situation I envisioned was when a single JVM hosts multiple (say N) isolated applications (in an app server for example) and when one such application is re-deployed.

In original design (webrev.02) each dequeued ClassValue.key is probed against all class maps that remain and belong to the other N-1 applications. In the alternative expunging design (webrev.03) the dequeued key just scans the array of weakly-referenced maps that the key was inserted into.

I created a benchmark to exercise such situation(s):

http://cr.openjdk.java.net/~plevart/misc/ClassValue.Alternative2/ClassValueExpungeBench.java

It measures the time of a hypothetical redeployment of one application in an app server where there are 16 such running applications. The measurement includes class-loading, GC time and initialization of ClassValue(s). Results show that alternative expunging design (webrev.03) doesn't bring any improvements (or that original supposedly sub-optimal expunging design (webrev.02) doesn't show any weaknesses) for the range of parameters exercised in the benchmark.

What this benchmark shows too is that original jdk 9 ClassValue has at least 2x overhead with cleanup compared to my designs (note that benchmark includes classloading time too).

 Regards, Peter


Best,

Michael

Am 05.05.2016 um 17:21 schrieb Peter Levart <peter.lev...@gmail.com <mailto:peter.lev...@gmail.com>>:

Hi Michael,


On 05/04/2016 06:02 PM, Michael Haupt wrote:
Hi Peter,

thank you for chiming in again! :-) I'll look at this in depth on Friday.

Good. Because I found bugs in expunging logic and a discrepancy of behavior when a value is installed concurrently by some other thread and then later removed while the 1st thread is still calculating the value. Current ClassValue re-tries the computation until it can make sure there were no concurrent changes to the entry during its computation. I fixed both things and verified that the behavior is now the same:

http://cr.openjdk.java.net/~plevart/misc/ClassValue.Alternative2/webrev.02/

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@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to