-
Notifications
You must be signed in to change notification settings - Fork 4
JVM annotations
How to get the JVM options added by QuickPerf?
Configure your test JVM
Β Β @HeapSize Β |Β @Xms Β |Β @Xmx Β |Β @UseGC (Next release) Β |Β @EnableGcLogging (Next release) Β |Β @JvmOptions
Verify heap allocation
Β Β @MeasureHeapAllocation Β |Β @ExpectMaxHeapAllocation Β |Β @ExpectNoHeapAllocation
Verify resident set size (RSS)
Β Β @MeasureRSS (Next release) Β |Β @ExpectMaxRSS (Next release)
Profile or check your JVM
Β Β @ProfileJvm Β |Β @ExpectNoJvmIssue
Some JVM annotations configure JVM options.
You can use @DebugQuickPerf to get the JVM options added by QuickPerf.
@DebugQuickPerf
JVM OPTIONS
-Xms20m
-Xmx20m
-XX:+UnlockExperimentalVMOptions
-XX:+AlwaysPreTouch
-XX:+UseEpsilonGC
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=C:\Users\JEANBI~1\AppData\Local\Temp\QuickPerf-16618400885811126911\heapDump.hprof
With this annotation, the test is executed in a specific JVM having the given heap size.
Parameter | Type | Meaning |
---|---|---|
value | long | Heap size value (Xms=Xmx) |
unit | AllocationUnit | Allocation unit |
@HeapSize(value = 20, unit = AllocationUnit.MEGA_BYTE)
With this annotation, the test is executed in a specific JVM having the given initial and minimum heap size value.
Parameter | Type | Meaning |
---|---|---|
value | long | Initial and minimum heap size value |
unit | AllocationUnit | Allocation unit |
@Xms(value = 20, unit = AllocationUnit.MEGA_BYTE)
With this annotation, the test is executed in a specific JVM having the given maximum heap size value.
Parameter | Type | Meaning |
---|---|---|
value | long | Maximum heap size value |
unit | AllocationUnit | Allocation unit |
@Xmx(value = 20, unit = AllocationUnit.MEGA_BYTE)
Available in next QuickPerf release
To specify a GC type.
Parameter | Type | Meaning | Default value |
---|---|---|---|
value | org.quickperf.jvm.gc.GC | GC type | GC.DEFAULT |
The following GC types are available:
- GC.EPSILON_GC: Epsilon GC - Doc 1, Epsilon GC - Doc 2
- GC.ZGC: ZGC - Doc
- GC.SHENANDOAH: Shenandoah - Doc
@UseGC(GC.EPSILON_GC)
Available in next QuickPerf release
To enable GC logging.
The path of the GC log file is displayed in the console:
GC log file: C:\Users\JEANBI~1\AppData\Local\Temp\QuickPerf-1127741195724299919\gc.log
This file can be analysed with the help of a GC log analyzer:
- GCViewer, GCViewer Download 1, GCViewer Download 2
- Censum
- GCeasy, the GC log file can be uploaded
- ...
With this annotation, the test is executed in a specific JVM having the given JVM options.
A tool developed by Chris Newland can be used to explore the available JVM options.
Parameter | Type | Meaning |
---|---|---|
value | String | JVM options |
The following annotations use ByteWatcher under the hood:
You can for example use @MeasureHeapAllocation and @ExpectMaxHeapAllocation to check the heap allocation cost of a large data structure (containing 1 000 000 elements for example) .
@ExpectNoHeapAllocation can be used to verify that the tested code does not allocate on heap.
You can measure heap allocation with this annotation.
The measured allocation is displayed in the console.
@RunWith(QuickPerfJUnitRunner.class)
public class ClassWithMethodAnnotatedWithMeasureAllocation {
@MeasureHeapAllocation
@JvmOptions("-XX:+UseCompressedOops -XX:+UseCompressedClassPointers")
// Heap allocation value depends on UseCompressedOops and UseCompressedClassPointers.
// QuickPerf works with JDK >= 7u40 where UseCompressedOops is enabled by default.
// UseCompressedClassPointers was introduced in JDK 8 and is enabled by default.
@Test
public void array_list_with_size_100_should_allocate_440_bytes() {
// java.util.ArrayList: 24 bytes
// +
// Object[]: 16 + 100 x 4 = 416
// = 440 bytes
ArrayList<Object> data = new ArrayList<>(100);
}
}
In console:
Measured heap allocation: 440.0 bytes
With this annotation, the test will fail if heap allocation is greater than expected.
Parameter | Type | Meaning |
---|---|---|
value | long | Allocation value |
unit | AllocationUnit | Allocation unit |
@ExpectMaxHeapAllocation(value = 440, unit = AllocationUnit.BYTE)
@Test
public void array_list_with_size_100_should_allocate_440_bytes() {
ArrayList<Object> data = new ArrayList<>(100);
}
With this annotation, the test will fail if heap allocation is detected.
Available in next QuickPerf release
You can use the two following methods of org.quickperf.jvm.heap.HeapDumper
class to dump the Java heap:
public static void dumpHeap(String fileName)
public static void dumpHeapWithOnlyLiveObjects(String fileName)
Several tools can be used to analyze the heap dump:
- Memory Analyzer Tool (MAT)
- JOverflow JMC plugin
- VisualVM
- YourKit (commercial)
- JProfiler (commercial)
- ...
@HeapSize(value = 50, unit = AllocationUnit.MEGA_BYTE)
@Test
public void do_something_and_dump_heap() {
IntegerAccumulator integerAccumulator = new IntegerAccumulator();
integerAccumulator.accumulateInteger(3_000_000);
HeapDumper.dumpHeap("C:\\Users\\Jean Bisutti\\heap-dump.hprof");
}
In console:
[QUICK PERF] Heap dump file
π C:\Users\Jean Bisutti\heap-dump.hprof
Available in next QuickPerf release
You can measure the Resident Set Size (RSS) with this annotation.
The measured RSS is displayed in the console.
Available in next QuickPerf release
With this annotation, the test will fail if the Resident Set Size (RSS) is greater than expected.
Parameter | Type | Meaning |
---|---|---|
value | long | value |
unit | AllocationUnit | RAM unit |
With the following annotations, the JVM is profiled with the JDK Flight Recorder (JFR), an event recorder built into the JVM.
The profiling content is saved in a .jfr file.
- Oracle JDK >= 1.7u40
- OpenJDK >= 11
- OpenJDK 8 with version >= 8u262
To profile the JVM with the JDK Flight Recorder (JFR).
The JFR file location is shown in the console. You can open it with Java Mission Control.
From next QuickPerf release, @ProfileJvm will also display some JVM profiling data (GC times, heap allocation estimation, exception numbers, ...) in standard output.
[QUICK PERF] JVM was profiled with Java Flight Recorder (JFR).
The recording file is available here: C:\Users\JEANBI~1\AppData\Local\Temp\QuickPerf-9292511997956298899\jvm-profiling.jfr
You can open it with Java Mission Control (JMC).
Where to find Java Mission Control? π https://tinyurl.com/find-jmc
From next QuickPerf release:
-----------------------------------------------------------------------------
ALLOCATION (estimations) | GARBAGE COLLECTION | THROWABLE
Total : 3,71Β GiB | Total pause: 929,136Β ms | Exception: 0
Inside TLAB : 3,7Β GiB | Longest GC pause: 149,625Β ms | Error: 36
Outside TLAB: 11,8Β MiB | | Throwable: 36
-----------------------------------------------------------------------------
COMPILATION | CODE CACHE
Number: 115 | The number of full code cache events: 0
Longest: 1,854Β s |
-----------------------------------------------------------------------------
JVM
Name: : OpenJDK 64-Bit Server VM
Version: : OpenJDK 64-Bit Server VM (11.0.1+13) for windows-amd64 JRE (11.0.1+13), built on Oct 6 2018 13:18:13 by "mach5one" with MS VC++ 15.5 (VS2017)
Arguments: : -XX:+FlightRecorder -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -Xms6g -Xmx6g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=C:\Users\JEANBI~1\AppData\Local\Temp\QuickPerf-7320430608814840691\heap-dump.hprof -DquickPerfToExecInASpecificJvm=true -DquickPerfWorkingFolder=C:\Users\JEANBI~1\AppData\Local\Temp\QuickPerf-7320430608814840691
-----------------------------------------------------------------------------
HARDWARE
Hardware threads: 8
Cores: 4
Sockets: 1
CPU:
Brand: Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz, Vendor: GenuineIntel
Family: <unknown> (0x6), Model: <unknown> (0x8e), Stepping: 0xa
Ext. family: 0x0, Ext. model: 0x8, Type: 0x0, Signature: 0x000806ea
Features: ebx: 0x02100800, ecx: 0x7ffafbbf, edx: 0xbfebfbff
Ext. features: eax: 0x00000000, ebx: 0x00000000, ecx: 0x00000121, edx: 0x2c100800
Supports: On-Chip FPU, Virtual Mode Extensions, Debugging Extensions, Page Size Extensions, Time Stamp Counter, Model Specific Registers, Physical Address Extension, Machine Check Exceptions, CMPXCHG8B Instruction, On-Chip APIC, Fast System Call, Memory Type Range Registers, Page Global Enable, Machine Check Architecture, Conditional Mov Instruction, Page Attribute Table, 36-bit Page Size Extension, CLFLUSH Instruction, Debug Trace Store feature, ACPI registers in MSR space, Intel Architecture MMX Technology, Fast Float Point Save and Restore, Streaming SIMD extensions, Streaming SIMD extensions 2, Self-Snoop, Hyper Threading, Thermal Monitor, Streaming SIMD Extensions 3, PCLMULQDQ, 64-bit DS Area, MONITOR/MWAIT instructions, CPL Qualified Debug Store, Virtual Machine Extensions, Enhanced Intel SpeedStep technology, Thermal Monitor 2, Supplemental Streaming SIMD Extensions 3, Fused Multiply-Add, CMPXCHG16B, xTPR Update Control, Perfmon and Debug Capability, Process-context identifiers, Streaming SIMD extensions 4.1, Streaming SIMD extensions 4.2, x2APIC, MOVBE, Popcount instruction, TSC-Deadline, AESNI, XSAVE, OSXSAVE, AVX, F16C, LAHF/SAHF instruction support, Advanced Bit Manipulations: LZCNT, SYSCALL/SYSRET, Execute Disable Bit, RDTSCP, Intel 64 Architecture, Invariant TSC
-----------------------------------------------------------------------------
There are several ways to get JMC:
- A jmc executable is available in the bin folder of some Oracle JDK (10 >= version >= 1.7u40)
- With Oracle
- With Azul Zulu Mission Control
- With Liberica Mission Control
- With Red Hat,
yum install rh-jmc
- The last JMC release can be found here (AdoptOpenJDK)
Today we consider this annotation as experimental.
With this annotation, JVM is profiled with Java Flight Recorder (JFR).
Based on the profiling, some JMC rules are evaluated. For each rule a score is attributed. The maximum score value is 100. The test will fail if one rule has a score greater than this expected (by default 60)
Things like significant primitives to object conversions can be detected:
π‘ With this annotation you can also detect that most of the time is spent to do garbage collection in your test.
π‘ If you have the following message in the console
Rule: Stackdepth Setting
Severity: WARNING
Score: 97
Message: Some stack traces were truncated in this recording.
then you can increase the stack depth value in this way:
@JvmOptions("-XX:FlightRecorderOptions=stackdepth=128")
Parameter | Type | Meaning | Default value |
---|---|---|---|
score | int | Rule score (<=100) | 60 |
π Β Core
π Β JVM
π Β SQL
π Β Scopes
π Β Create an annotation
π Β JUnit 4
π Β JUnit 5
π Β TestNG
π Β Spring
π Β Detect and fix N+1 SELECT
π Β Maven performance
π Β Spring Boot - JUnit 4
π Β Spring Boot - JUnit 5
π Β Micronaut Data - JUnit 5
π Β Micronaut - Spring - JUnit 5
π Β Quarkus - JUnit 5
π Β FAQ
π Β QuickPerf code