The JVM is a great VM for running server-side applications, but if you just want to run java-written scripts frequently, or if you’re running ancillary Java programs like monitoring or log collection, the requirements are different than in everyday applications:

  1. Fast start, low noise.
  2. Low cost, saving CPU, memory and threads.
  3. Low disturbance, does not interfere with the operation of the main application.


First, learn from failure

For the first time, look at what arguments jmap and jStack use and find that they all have a single -xMS8m (run JPS -v to see them when they run, source validation JDK7 see makefile.launcher, JDK8 see compilelaunchers.gmk).

In addition, the legendary -client is also invalid on multi-core Linux servers.

Now I’m going to do my own thing, Deserve to go up first to run the script “- Xloggc: gc. The log – XX: XX: + PrintGCDetails – + PrintGCDateStamps – XX: + PrintGCApplicationStoppedTime”, In gc.log there are the actual startup parameters, the GC log, and the memory usage for each generation printed at the end.

Second, the long-term running a pidstat -l 1 | grep XXX process monitoring CPU consumption

Finally, jStack takes a look at the process to see how many threads are running in it, which is a scary number for a default JVM.

Class loading and compiling

1 -Xverify:none

Experience from optimizing Eclipse startup speed says that turning off Java classloading validation can speed up startup by 10-15%.

2 Set the compile level

Jit-compiled code is faster and less CPU-intensive than interpreted execution of bytecode, but compilation itself requires CPU and additional compilation threads. Temporarily add “-xx :+PrintCompilation” to the startup script to observe the compilation.

If the script code is simply run once, such as vjMxcli in vjTools, it is recommended not to JIT compilation. After compilation, it is not needed. Disable it: -djava.com piler=NONE

If the script will be used for circular calculations, such as vjMap in VjTools, it is recommended to turn on multi-layer compilation and statically compile the running method from the start, rather than waiting for the method to be called 10,000 times. Multi-layer compilation is enabled by default in JDK8, explicitly: -xx :+TieredCompilation.

However, opening multi-layer compilation will also lead to more compilation tasks at the beginning of the program, eating more CPU, you can explicitly turn off multi-layer compilation -xx: -tieredCompilation to compare, comprehensive evaluation of the performance improvement brought by it, the life cycle of the script, and additional CPU expenditure.

3 Setting of compile thread

On a 24-core server, there are 4 C1 compilation threads and 8 C2 compilation threads by default (for multi-layer compilation). It is recommended to set this to a minimum of -xx :CICompilerCount=2 in consideration of low cost.

Future Hacks -AOT

JIT is not cool, ahead-of-time (AOT) compilation is better. There is an experimental JAOTC from the Hotspot compiler team in JDK9, another option is SubstrateVM in the GraalVM family bucket, which supports JDK8. Both are based on Graal, which I haven’t played yet.

3. GC Settings

These scripts, helper processes generally do not mind GC latency, suggest using the most metric -XX:+UseSerialGC serial collection algorithm, greatly reduce the number of GC threads generated by other GC algorithms, to ensure that their own GC will not affect the main application.

If you still want to use the parallel algorithm, you must set the number of GC threads. If you use the default values, the number of YGC and CMS GC threads is 18 and 5 respectively on a 24-core machine. Once GC occurs, it takes up a lot of CPU cores and has a huge impact on the main application. Set it to -xx arallelGCThreads=2. -xx :ConcGCThreads = 1

Four, memory Settings

The JVM’s heap memory expansion is not as smart as it should be, and when -xMS and -xmx differ, the generation size is even more confusing without specifying the generation ratio. It is recommended to fully set the most appropriate value based on the actual post-run occupancy and GC logs.

Scripts that run quickly once are almost useless in the old generation, but larger in the new generation.

-Xms96m -Xmx96m -Xmn64m

For long-term operation, it is generally set to 1:1.

-Xms256m -Xmx256m -XX:NewRatio=1

Memory per thread goes back from the default of 1M to 256K: -xss256K

Permanent generation can also be set, unfortunately jdk7/8 parameters are not compatible, using Java -version to obtain the version number is too expensive, so if you know the JDK version can be set, otherwise forget.

Five, the other

If you don’t have an autoBoxing of int ->Integer, open -xx :AutoBoxCacheMax=20000

If there are other black technology, please add.

Six, the summary

Thank you to see here, this topic is more partial door, secluded place can be someone line.

A quick execution of a script with the JIT turned off might look something like this:

-Xms96m -Xmx96m -Xmn64m -Xss256k -XX:+UseSerialGC -Djava.compiler=NONE -Xverify:none -XX:AutoBoxCacheMax=20000

A helper program. The startup command looks something like this

-Xms256m -Xmx256m -XX:NewRatio=1 -Xss256k -XX:+UseSerialGC -XX:-TieredCompilation -XX:CICompilerCount=2 -Xverify:none -XX:AutoBoxCacheMax=20000

VJTools several tools startup scripts, according to this standard has been rewritten.

Write at the end: welcome to pay attention to the message, welcome to pay attention to xiaobian!