Presentation Are your GC logs speaking to you, the G1GC edition

Oracle's version of Java 7 saw the release of a new collector, the G1GC. This collector is unlike all the other collectors found in the Oracle JVM in that it instead of generational spaces, it organizes Java heap into regions. There are a number of other features that make this memory management scheme different than other collectors. Even though this collector is designed to be self-tuning, there are occasions when hand tuning will offer better results. In this session we will use the GC logs to expose some of the inner workings of the G1 collector with an eye on key metrics that can be helpful in deciding how to tune.

Speakers


PDF: slides.pdf

Slides

Do Your GC Logs

Do Your GC Logs Speak To You Visualizing G1GC, the Garbage First Garbage Collector Copyright 2013 Kodewerk Ltd. All rights reserved

About Me

About Me Kodewerk tm Java Performance Services • Consultant (www.kodewerk.com) • performance tuning and training • Helped establish www.javaperformancetuning.com • Member • Other of Java Champion program stuff... (google is you care to) Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services • Most • recently founded a company jClarity • We are well on the road to delivering the next generation of advanced performance tooling • Come visit our booth!!!! Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services Disclaimer The resemblance of any opinion, recommendation or comment made during this presentation to performance tuning advice is merely coincidental. Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services Why collect GC logs? Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services GC logs contain the information you need to make informed choices about how to tune Java Memory managemet Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services What is the performance impact of logging GC in production? Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services How do I get a GC log? Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services -verbose:gc (not recommended) -Xloggc:gc.log (recommended) -XX:+UseGCLogFileRotation (7.0 feature) -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=1g -XX:+PrintGCDetails -XX:+PrintTenuringDistribution -XX:+PrintHeapAtGC Copyright 2013 Kodewerk Ltd. All rights reserved

tm

tm eden S0 S1 reserved Java Performance Services GC tenured reserved Kodewerk Generational Split memory into different memory pools Objects allocated in young and eventually moved to tenured Pools cleaned via mark/sweep collector Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk Mark tm Java Performance Services Sweep Review Allocation failure triggers a collection initial occupancy fraction (tenured Call to safe-point application threads Find all GC roots Mark all live objects by tracing references from roots Reclaim unreachable or evict survivors fix all dangling pointers Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk What tm Java Performance Services is a Safe-Point? A point in a threads execution when it can safely be interrupted compilers salt code with calls to safe-point capture and block application threads Frequent safe-pointing creates scheduling pressure Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk What tm Java Performance Services is a GC Root? Two types of pointers interal point pointer to data is contained within a memory pool external pointer pointer to data is outside of the memory pool GC Roots are external pointers Copyright 2013 Kodewerk Ltd. All rights reserved

Where’s Waldo?

Where’s Waldo? eden S0 S1 tenured Aside from Perm gen, globals, registers, stack frames, locks, VM data structures roots for; tenured are in young young are in tenured Copyright 2013 Kodewerk Ltd. All rights reserved reserved tm Java Performance Services reserved Kodewerk

KodewerkWhat’s

KodewerkWhat’s tm Java Performance Services in a Pause Safe-pointing (2x context switch) scan for roots objects that are live by definition mark everything reachable from a root trace live objects sweep (reallocate by copy or compaction) finding and repoint dangling pointers Copyright 2013 Kodewerk Ltd. All rights reserved

Challenges

Challenges Kodewerk tm Java Performance Services Applications need to process more data than they ever had to translates to larger working sets GC pause dominated by working set size scan for roots cost dominated by heap size larger heaps and working set == longer pauses Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk Generational tm Java Performance Services GC Good at ignoring dead objects Not so good with large heaps Not so good with large live sets Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services How can we disentangle pause time from heap size? Ignore long lived objects? Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services IOWs..... I would like to maximize MMU so that we can work with larger working sets without suffering the pause? Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services Enter Regional Collectors Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk Regional tm Java Performance Services Collectors Several (hybrid) implementations still generational Oracle G1GC IBM Balance Azul C4 Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk G1 tm Java Performance Services Heap Structure Heap divided into ~2000 uniformly sized regions size ranges from 1m-32m size determined ergonomically -XX:G1HeapRegionSize= Copyright 2013 Kodewerk Ltd. All rights reserved

G1GC

G1GC Kodewerk tm Java Performance Services Self tuning specify minimal configurations max heap size max pause time pause time interval Region set sizes adapt to meet pause over interval goal goal not a guarantee Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services Region Sets At any time any region can belong to; eden survivor old humungous really really big un-used regions are taken from and returned to un-used O S E O O E E H O O Copyright 2013 Kodewerk Ltd. All rights reserved H S H

Kodewerk

Kodewerk tm Java Performance Services Region Sets Un-used is the list of free regions Objects are created in Eden Survivor and old serves the same purpose as they do in a generational heap Objects larger than 50% of a region are humungous combine contiguous regions to create a larger space Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk Remember tm Java Performance Services Set (RSet) Set of cards that track external pointers into its region record pointer to RSet mark RSet as mutated Cost <5% of memory write memory barrier (visibility) indirection Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk Collection tm Java Performance Services Sets (CSET) Find a set of regions that may be swept within a given pause time goal time to collect a region is known Focus on regions “ripe” for collection empty is trivial almost empty is cheap almost full is expensive Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services Collection Young gen mark and sweep evacuate all reachable objects to a new region per region evacuation pauses Mixed collections Tenured is a concurrent mark Mixed: YG sweep includes old gen regsions Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk 63.170: [GC pause (young) tm Desired survivor size 524288 bytes, new threshold 15 (max 15) 82912 bytes, 82912 total - age 2: 230888 bytes, 313800 total Java Performanceage 1: Services - , 0.00333500 secs] [Parallel Time: 2.8 ms] [GC Worker Start (ms): 63170.2 63170.2 63170.2 63170.3 63170.3 63172.7 63172.8 63172.8 Avg: 63171.2, Min: 63170.2, Max: 63172.8, Diff: 2.5] [Ext Root Scanning (ms): 1.3 1.8 1.2 1.0 1.1 0.0 0.0 0.0 Avg: 0.8, Min: 0.0, Max: 1.8, Diff: 1.8] [Update RS (ms): 0.0 0.0 0.1 0.2 0.1 0.0 0.0 0.0 Avg: 0.0, Min: 0.0, Max: 0.2, Diff: 0.2] [Processed Buffers : 0 0 4 3 5 0 0 0 Sum: 12, Avg: 1, Min: 0, Max: 5, Diff: 5] [Scan RS (ms): 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 Avg: 0.0, Min: 0.0, Max: 0.0, Diff: 0.0] [Object Copy (ms): 1.0 0.6 1.1 1.1 1.1 0.0 0.0 0.0 Avg: 0.6, Min: 0.0, Max: 1.1, Diff: 1.1] [Termination (ms): 0.2 0.2 0.3 0.2 0.2 0.1 0.0 0.0 Avg: 0.2, Min: 0.0, Max: 0.3, Diff: 0.3] [Termination Attempts : 4 1 6 2 4 1 1 1 Sum: 20, Avg: 2, Min: 1, Max: 6, Diff: 5] [GC Worker End (ms): 63172.8 63172.8 63172.8 63172.8 63172.8 63172.8 63172.8 63172.8 Avg: 63172.8, Min: 63172.8, Max: 63172.8, Diff: 0.0] [GC Worker (ms): 2.6 2.6 2.6 2.5 2.5 0.1 0.0 0.0 Avg: 1.6, Min: 0.0, Max: 2.6, Diff: 2.6] [GC Worker Other (ms): 0.2 0.2 0.2 0.2 0.3 2.6 2.7 2.8 Avg: 1.2, Min: 0.2, Max: 2.8, Diff: 2.6] [Clear CT: 0.1 ms] [Other: 0.4 ms] [Choose CSet: 0.0 ms] [Ref Proc: 0.4 ms] [Ref Enq: 0.0 ms] [Free CSet: 0.0 ms] [Eden: 3072K(3072K)->0B(2048K) Survivors: 1024K->1024K Heap: 6999K(10M)->5288K(10M)] [Times: user=0.02 sys=0.00, real=0.00 secs] Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services 63.170: [GC pause (young) Desired survivor size 524288 bytes, new threshold 15 (max 15) - age 1: 82912 bytes, - age 2: 230888 bytes, 82912 total 313800 total , 0.00333500 secs] Pure evacuation pause of young gen regions lasting 0.00333500 seconds started 63.170 seconds after VM startup Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services 63.170: [GC pause (young) Desired survivor size 524288 bytes, new threshold 15 (max 15) - age 1: 82912 bytes, - age 2: 230888 bytes, 82912 total 313800 total , 0.00333500 secs] Desired survivor size is 524288 bytes Max tenuring threshold is 15 Calculated threshold is 15 note: bytes @ age1 + age 2 < desired Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services [Eden: 3072K(3072K)->0B(2048K) Survivors: 1024K->1024K Heap: 6999K(10M)->5288K(10M)] [Times: user=0.01 sys=0.00, real=0.00 secs] Evacuation changes memory consumption reported on Report format for Eden, survivor, and total heap before(size)->after(size) old must be calculated Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk 63.170: [GC pause (young) tm Desired survivor size 524288 bytes, new threshold 15 (max 15) 82912 bytes, 82912 total - age 2: 230888 bytes, 313800 total Java Performanceage 1: Services - , 0.00333500 secs] [Parallel Time: 2.8 ms] [GC Worker Start (ms): 63170.2 63170.2 63170.2 63170.3 63170.3 63172.7 63172.8 63172.8 Avg: 63171.2, Min: 63170.2, Max: 63172.8, Diff: 2.5] [Ext Root Scanning (ms): 1.3 1.8 1.2 1.0 1.1 0.0 0.0 0.0 Avg: 0.8, Min: 0.0, Max: 1.8, Diff: 1.8] [Update RS (ms): 0.0 0.0 0.1 0.2 0.1 0.0 0.0 0.0 Avg: 0.0, Min: 0.0, Max: 0.2, Diff: 0.2] [Processed Buffers : 0 0 4 3 5 0 0 0 Sum: 12, Avg: 1, Min: 0, Max: 5, Diff: 5] [Scan RS (ms): 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 Avg: 0.0, Min: 0.0, Max: 0.0, Diff: 0.0] [Object Copy (ms): 1.0 0.6 1.1 1.1 1.1 0.0 0.0 0.0 Avg: 0.6, Min: 0.0, Max: 1.1, Diff: 1.1] [Termination (ms): 0.2 0.2 0.3 0.2 0.2 0.1 0.0 0.0 Avg: 0.2, Min: 0.0, Max: 0.3, Diff: 0.3] [Termination Attempts : 4 1 6 2 4 1 1 1 Sum: 20, Avg: 2, Min: 1, Max: 6, Diff: 5] [GC Worker End (ms): 63172.8 63172.8 63172.8 63172.8 63172.8 63172.8 63172.8 63172.8 Avg: 63172.8, Min: 63172.8, Max: 63172.8, Diff: 0.0] [GC Worker (ms): 2.6 2.6 2.6 2.5 2.5 0.1 0.0 0.0 Avg: 1.6, Min: 0.0, Max: 2.6, Diff: 2.6] [GC Worker Other (ms): 0.2 0.2 0.2 0.2 0.3 2.6 2.7 2.8 Avg: 1.2, Min: 0.2, Max: 2.8, Diff: 2.6] [Clear CT: 0.1 ms] [Other: 0.4 ms] [Choose CSet: 0.0 ms] [Ref Proc: 0.4 ms] [Ref Enq: 0.0 ms] [Free CSet: 0.0 ms] [Eden: 3072K(3072K)->0B(2048K) Survivors: 1024K->1024K Heap: 6999K(10M)->5288K(10M)] [Times: user=0.02 sys=0.00, real=0.00 secs] Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services [Parallel Time: 2.8 ms] Total elapsed time for parallel worker threads Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services [GC Worker Start (ms): 63170.2 63170.2 63170.2 63170.3 63170.3 63172.7 63172.8 63172.8 Avg: 63171.2, Min: 63170.2, Max: 63172.8, Diff: 2.5] ..... [GC Worker End (ms): 63172.8 63172.8 63172.8 63172.8 63172.8 63172.8 63172.8 63172.8 Avg: 63172.8, Min: 63172.8, Max: 63172.8, Diff: 0.0] Time stamp for when each GC worker started and then ended Statistical summary of record Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services [GC Worker (ms): 2.6 2.6 2.6 2.5 2.5 0.1 0.0 0.0 Avg: 1.6, Min: 0.0, Max: 2.6, Diff: 2.6] [GC Worker Other (ms): 0.2 0.2 0.2 0.2 0.3 2.6 2.7 2.8 Avg: 1.2, Min: 0.2, Max: 2.8, Diff: 2.6] Total concurrent time from start and stop record Other is activity not accounted for in the summary records Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services [Ext Root Scanning (ms): 1.3 1.8 1.2 1.0 1.1 0.0 0.0 0.0 Avg: 0.8, Min: 0.0, Max: 1.8, Diff: 1.8] Per-thread time to scan for roots Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services [Update RS (ms): 0.0 0.0 0.1 0.2 0.1 0.0 0.0 0.0 Avg: 0.0, Min: 0.0, Max: 0.2, Diff: 0.2] [Processed Buffers : 0 0 4 3 5 0 0 0 Sum: 12, Avg: 1, Min: 0, Max: 5, Diff: 5] Per-thread time to process update buffers to RSet Mutator threads record changes in an update buffer Number of buffers processed by each thread Statistical summary for each record Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services [Scan RS (ms): 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 Avg: 0.0, Min: 0.0, Max: 0.0, Diff: 0.0] Per-thread time to process RSets [Object Copy (ms): 1.0 0.6 1.1 1.1 1.1 0.0 0.0 0.0 Avg: 0.6, Min: 0.0, Max: 1.1, Diff: 1.1] Per-thread time spent copying objects in the CSet to other regions Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services [Termination (ms): 0.2 0.2 0.3 0.2 0.2 0.1 0.0 0.0 Avg: 0.2, Min: 0.0, Max: 0.3, Diff: 0.3] [Termination Attempts : 4 1 6 2 4 1 1 1 Sum: 20, Avg: 2, Min: 1, Max: 6, Diff: 5] Per-thread time of offer to terminate Follow up is number of termination attempts maybe offered work from other threads queue work stealing Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services [Termination (ms): 0.2 0.2 0.3 0.2 0.2 0.1 0.0 0.0 Avg: 0.2, Min: 0.0, Max: 0.3, Diff: 0.3] [Termination Attempts : 4 1 6 2 4 1 1 1 Sum: 20, Avg: 2, Min: 1, Max: 6, Diff: 5] Per-thread time of offer to terminate Follow up is number of termination attempts maybe offered work from other threads queue work stealing Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services [Clear CT: 0.1 ms] Clear card tables single threaded pause event Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services [Other: 0.4 ms] [Choose CSet: [Ref Proc: 0.0 ms] 0.4 ms] [Ref Enq: 0.0 ms] [Free CSet: 0.0 ms] Other tasks reference processing reference enqueuing freeing the collection set data structure Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk 63.170: [GC pause (young) tm Desired survivor size 524288 bytes, new threshold 15 (max 15) 82912 bytes, 82912 total - age 2: 230888 bytes, 313800 total Java Performanceage 1: Services - , 0.00333500 secs] [Parallel Time: 2.8 ms] [GC Worker Start (ms): 63170.2 63170.2 63170.2 63170.3 63170.3 63172.7 63172.8 63172.8 Avg: 63171.2, Min: 63170.2, Max: 63172.8, Diff: 2.5] [Ext Root Scanning (ms): 1.3 1.8 1.2 1.0 1.1 0.0 0.0 0.0 Avg: 0.8, Min: 0.0, Max: 1.8, Diff: 1.8] [Update RS (ms): 0.0 0.0 0.1 0.2 0.1 0.0 0.0 0.0 Avg: 0.0, Min: 0.0, Max: 0.2, Diff: 0.2] [Processed Buffers : 0 0 4 3 5 0 0 0 Sum: 12, Avg: 1, Min: 0, Max: 5, Diff: 5] [Scan RS (ms): 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 Avg: 0.0, Min: 0.0, Max: 0.0, Diff: 0.0] [Object Copy (ms): 1.0 0.6 1.1 1.1 1.1 0.0 0.0 0.0 Avg: 0.6, Min: 0.0, Max: 1.1, Diff: 1.1] [Termination (ms): 0.2 0.2 0.3 0.2 0.2 0.1 0.0 0.0 Avg: 0.2, Min: 0.0, Max: 0.3, Diff: 0.3] [Termination Attempts : 4 1 6 2 4 1 1 1 Sum: 20, Avg: 2, Min: 1, Max: 6, Diff: 5] [GC Worker End (ms): 63172.8 63172.8 63172.8 63172.8 63172.8 63172.8 63172.8 63172.8 Avg: 63172.8, Min: 63172.8, Max: 63172.8, Diff: 0.0] [GC Worker (ms): 2.6 2.6 2.6 2.5 2.5 0.1 0.0 0.0 Avg: 1.6, Min: 0.0, Max: 2.6, Diff: 2.6] [GC Worker Other (ms): 0.2 0.2 0.2 0.2 0.3 2.6 2.7 2.8 Avg: 1.2, Min: 0.2, Max: 2.8, Diff: 2.6] [Clear CT: 0.1 ms] [Other: 0.4 ms] [Choose CSet: 0.0 ms] [Ref Proc: 0.4 ms] [Ref Enq: 0.0 ms] [Free CSet: 0.0 ms] [Eden: 3072K(3072K)->0B(2048K) Survivors: 1024K->1024K Heap: 6999K(10M)->5288K(10M)] [Times: user=0.02 sys=0.00, real=0.00 secs] Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services 63.233: [GC pause (young) Desired survivor size 524288 bytes, new threshold 1 (max 15) - age 1: 1275728 bytes, 1275728 total - age - age 2: 3: 81624 bytes, 230888 bytes, 1357352 total 1588240 total (initial-mark), 0.00522500 secs] Old space initial-mark has been piggybacked onto the evacuation phase Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services 63.239: [GC concurrent-root-region-scan-start] 63.239: [GC concurrent-root-region-scan-end, 0.0006690] 63.239: [GC concurrent-mark-start] 63.246: [GC concurrent-mark-end, 0.0066900 sec] Several scanning phases account fo mutations while running Concurrent phases, start and duration scan from root directly reachable from survivor spaces Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services 63.246: [GC remark 63.247: [GC ref-proc, 0.0000480 secs], 0.0014730 secs] [Times: user=0.01 sys=0.00, real=0.00 secs] Stop-the-world remark starts @ 63.246 duration: 0.0014730 Includes reference processing starts @ 63.247 duration: 0.0000480 Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services 80.197: [GC concurrent-cleanup-start] 80.197: [GC concurrent-cleanup-end, 0.0000740] Return empty regions back to unused Concurrent time of 0.0000749 seconds Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services Other Records [GC concurrent-mark-reset-for-overflow] Global marking stack was full heap is too small scan of old started too late must start over expensive failure Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services Flags and Stuff -XX:+UseG1GC -mx, -mn -XX:MaxGCPauseMillis=200 -XX:GCPauseIntervalMillis=1000 -XX:InitiatingHeapOccupancyPercent=45 -XX:NewRatio=2 -XX:SurvivorRatio=8 Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services Flags and Stuff -XX:MaxTenuringThreshold=15 -XX:ParallelGCThreads=n -XX:ConcGCThreads=n -XX:G1ReservePercent=n -XX:G1HeapRegionSize=n numerous other flags that get hairy Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services Flags and Stuff Does not respond well to aggressive pause time goals Setting -mn, SurvivorRatio, or a number of other flags *will* cause the pause time to be ignored very very difficult to tune Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services GC Jitter??? FX application to flip screen between black and white on each vsync 60hz signal==16.7ms update interval 10Gig heap, 10ms over 200ms pause time goal never hit it! Copyright 2013 Kodewerk Ltd. All rights reserved

Kodewerk

Kodewerk tm Java Performance Services Wanna learn more? “Become Proficient in Java Performance Tuning”, May 27-30, Stockholm www.kodewerk.com And for tooling www.jclarity.com Copyright 2013 Kodewerk Ltd. All rights reserved