Java Garbage Collection Time? - java

I have a very performance sensitive application in Java. (I know I should actually use C or something else. But it's Java now.) I'm trying to avoid creating and throwing away objects. Now I need to know how much garbage collecting is going on still.
How can I find out ?
If possible I would like to have a sort of number in milliseconds or nanoseconds something that doesn't require installation of more software.

Or you can let JVM print the GC activity.. These settings I have:
-verbose:gc -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -XX:+PrintTenuringDistribution -Xloggc:logs/gc.log
GC activity is printed to a file logs/gc.log..

You can use tools like VisualVM to monitor application activity. Make sure you are using appropriate GC alogorithms.
Oracle JVM provides multiple types of Garbage Collectors:
The throughput collector
The concurrent low pause collector
The incremental (sometimes called train) low pause collector:
Read more on these collectors here.

You can use VisualVm for this, it is exactly what you need.
As you can see below you have GC activity which is very useful:
Beside the GC Activity you have a lot of details there like : heap usage, cpu usage, object instances usage etc.

Jprofiler ,which Enables both memory profile to assess memory usage and dynamic allocation leaks and CPU profiling to assess thread conflicts.

Related

Can I stop JVM performing garbage collection?

I want to know if there is a way to stop and start the JVM performing Garbage Collection during runtime.
If there is not, why not? Surely this feature would make Java more suitable for safety critical applications?
Actually, there is a way to stop Java GC. Just use the Epsilon GC algorithm that was introduced as an experimental feature in Java 11. Just add the following two arguments to your JVM's startup script:
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
All or Nothing
Now just keep in mind that this Java GC algorithm does no GC at all. So if you do any object allocation in your code, eventually you'll hit an OutOfMemoryError and your app will crash. But if your JVM is short lived, and you don't think that's an issue, give Epsilon GC a try.
Just remember it's all or nothing. You can't force Java GC and you can't stop Java GC from happening if you use any of the other garbage collectors. The collector is non-deterministic, so control by programmers or admins just isn't possible out of the box.
By default the JVM runs the JVM only needed. This means you can't turn off the GC or your program will fail.
The simplest way to avoid stopping the JVM is;
use a very small eden size so when it stops it will be less than some acceptable time.
or make the eden size very large and delay the GC until it hardly matters. e.g. you can reduce you garbage rate and run for 24 hours or longer between minor GCs.

JVM performance with these garbage collection settings

I have an enterprise level Java application that serves a few thousand users per day. This is a JAXB web service on weblogic 10.3.6 (Java 1.6 JVM), using Hibernate to hit an Oracle database. It also calls other web services.
We have it tuned the following GC settings on our production system:
-server -Xms2048m -Xmx2048m -XX:PermSize=512m -XX:MaxPermSize=512m
What is the effect of this GC sizing? The hardware has more than enough capacity to handle it.
I know that this sets the heap size and perm gen at a stable level. But what's the impact of that when you eventually have to do garbage collection?
To me it seems that it would make GC happen less frequently, but take longer when it does happen. Does that sound correct?
I would say please monitor the GC before deciding on the sizing as you never know how the application will behave under load. Have a look at this link and this it has some good references about GC and tools to calculate the same.
it would make GC happen less frequently, but take longer when it does happen
It might, it depends on your use case. You might even find that the GC is shorter in rare case.
A 2 GB heap isn't that much and I would use up to 26 GB without worrying about heap size. Above this size memory accesses are a little slower or use more memory.
Setting -Xmx & -Xms and PermSize & MaxPermSize to equal sizes will stop the JVM from resizing the heaps based on your requirement. These resizes are expensive as they trigger a Full GC.
-server will allow the JVM to make use of Server Compiler which will do more aggressive optimizations before compiling your code to native assembly instructions. Although now-a-days any machine with 2 or more cores and 2GB+ of memory will have server compiler on by default.
Increasing the memory doesn't always fix a problem. Sometimes adding more memory will be an overhead.
If you need details regarding GC, you can try this link
The very reason to tune something is to improve your application's performance and there by achieve your throughput and latency goals.

Is there a cookbook guide for GC problems?

Almost everyone eventually runs into GC issues with Java.
Is there a cookbook guide or semi-automated tool to tune GC for Java?
My rationale is this:
Almost anyone eventually has these problems
There are many possible factors (say 20) out of which only a few affect your problem.
Most people don't know how to identify the key factors so GC tuning is more like a black art than a science.
Not everyone uses a HotSpot VM. Different Sun versions have different GC characteristics.
There is little incentive to experiment (like run the VM with slightly different settings every day to see how they play out).
So the question really is: Is there something that I can use in a check-list manner? Or maybe even a tool that analyzes GC logs or heap dumps and gives me specific hints where to look (instead of telling me "95% of the data is allocated in objects of the type byte[]" which is basically useless).
Related questions:
Appropriate Tomcat 5.5 start-up parameters to tune JVM for extremely high demand, large heap web application? which is very specific. My question is more wide.
What are the best garbage collection settings for client side? Again very narrow scope
Does anyone know of a good guide to configure GC in Java? HotSpot only
JVM memory management & garbage collection book? is 80% there but I'm missing the checklist/cookbook/for-dummies approach.
Out of various resources I have compiled a sanity checklist that I use to analyze GC behavior and performance of my applications. These guidelines are general and apply to any vendor-specific JVM but contain also HotspotVM-specific information for illustration.
Disable Explicit GC. Explicit GC is a bad coding practice, it never helps. Use -XX:+DisableExplicitGC.
Enable Full GC logging. Lightweight yet powerful.
Compute Live Data Set, Allocation Rate, and Promotion Rate. This will tell you if you need a bigger Heap or if your eg. Young Gen is too small, or if your Survivor spaces are overflowing, etc.
Compute total GC time, it should be <5% of total running time.
Use -XX:+PrintTenuringDistribution -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=jvm.log -XX:+HeapDumpOnOutOfMemoryError -Xloggc:gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -showversion
Consider additional means of collecting information about your GC. Logging is fine but there are sometimes available lightweight command-line tools that will give you even more insight. Eg. jstat for Hotspot which will show you occupation/capacity of Eden, Survivor and Old Gen.
Collect Class Histograms These are lightweigh and will show you the content of the heap. You can take snapshots whenever you notice some strange GC activity, or you can take them before/after Full GC:
Content of the OldGen space: You can find out which objects reside in the OldGen. You need to print histograms before and after Full GC. And since a YoungGen collection is executed before the Full GC, these Histograms will show you the content of the Old generation. Use -XX:+PrintClassHistogramBeforeFullGC -XX:+PrintClassHistogramAfterFullGC.
Detecting prematurely promoted objects: To determine if any instances are promoted early, you need to study the Histograms to see which classes are expected to reside in the OldGen and which classes should be seen only in the YoungGen. This cannot be done automatically, you need to reason about the purpose of each class and its instance to determine if the object is temporary or not.
Consider different GC Algorithm. The VMs usually come with several different GC implementations that are providing various tradeoffs : throughput, footprint, pause-less/short-pauses, real-time, etc. Consider the options you have and pick the one that suites your needs.
Beware of finalize(). Check that GC keeps up with classes using finalize(). The execution of this method may be quite costly and this can impact GC and application throughput.
Heap Dumps. This is the first step that is heavyweight and will impact the running application. Collect the Heap Dump to further study the heap content or to confirm a hypothesis observed in step 4.
Resources used:
Books:
Java Performance - practical guide
The Garbage Collection Handbook - theory explained
Talks/Articles:
Java One 2012 Advanced JVM Tuning
From Java code to Java heap
Java One 2012 G1 Garbage Collector Performance Tuning
Garbage Collection Tuning Guide
Mailing Lists:
OpenJDK Hotspot GC Use
References for various GC information:
Oracle
Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine
and this also
Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning
IBM
Fine Tuning Garbage Collection [link dead]
Extensible Verbose Toolkit
SAP JVM
Memory Management (Garbage Collection)
Detecting Memory Leaks
Detecting Hanging / Looping VMs
Analyzing Out-of-Memory Situations
Sorry I don't know much about SAP but have provided some things I have found.
As for a cookbook, tuning is most likely application specific at this level, but it is an interesting topic.
ADDENDUM
You also mentioned analysis tools. Some candidates are listed here:
Know of any Java garbage collection log analysis tools?

How can I disable Java garbage collector?

We have a PHP webapp that calls a Java binary to produce a PDF report (with JasperReports). The Java binary outputs the PDF to standard output and exits; the PHP then sends the PDF to browser. This Java command lasts about 3 to 6 seconds, and I think when it lasts 6 second it's because the GC kicks in. I would like to disable the GC because anyway when the command exits all memory is returned.
I would like to know how to disable it for Java 1.4.2 and for Java 1.6.0 because we are currently testing both JVM to see which performs faster..
It sounds like you are trying to save time, but going about it the wrong way. The time saved in disabling garbage collection would be trivial (for a single task) compared to the time taken to launch and shutdown the java process. You might want to consider having a java process launch that you can ask multiple times to do the work you require if run-time performance is your goal.
There is no way to disable garbage collection entirely. Garbage collection is only run when the JVM runs out of space, so you could give the program more memory. Add these command line options to the Java command
-Xmx256M -Xms256M
This gives the program 256Mb of ram (the default is 64Mb). Garbage collection will not take 3 seconds for a default size JVM though, so you might want to investigate more closely what the program is doing. Yourkit profiler is very useful for figuring out what is taking a long time.
GC only kicks in when JVM is short on memory, so you either GC or die. Try turning on verbose GC and see if it actually takes significant amount of time.
java -verbose:gc
Java 11 comes with an no-op garbage collector.
It can be enabled by the -XX:+UseEpsilonGC option at JVM start.
According to the JEP decription one of its goals is to make certain short-lived jobs more efficient, what might be you use case:
Extremely short lived jobs. A short-lived job might rely on exiting quickly to free the resources (e.g. heap memory). In this case, accepting the GC cycle to futilely clean up the heap is a waste of time, because the heap would be freed on exit anyway. Note that the GC cycle might take a while, because it would depend on the amount of live data in the heap, which can be a lot.
Java 11 gives you the binary option to either have Java GC on, or have Java GC turned off. To turn off Java GC you use the Epsilon Garbage Collector which must be turned off on the command line. On Java 11, use the following two JVM arguments:
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
Without the UnlockExperimentalVMOptions argument, the JVM will fail to start, so make sure it's included.
Can't Stop Java GC
Unfortunately, if you're not using Epsilon GC, there is no way to disable, stop or prevent garbage collection from happening. Just like not being able to trigger GC, you can't stop Java GC either. The algorithms are non-deterministic. Only the JVM can control when they occur.
You can use the -Xmx option to set the maximum heap size; using a larger heap should prevent the VM from runnning out of memory and, thereby, requiring garbage collection so soon.
Are you sure that it is garbage collection causing the slowdown? Have you run java with -verbose:gc to see what is happening?
You cannot disable garbage collection on the JVM. You could however look at tuning the garbage collector for better performance.
Contrary to what everyone else has said, there is a way to suspend GC, though it's very convoluted.
If you call a native function via JNI, in between the native code calling GetPrimitiveArrayCritical and ReleasePrimitiveArrayCritical, GC is suspended. It has to do this because it is the mechanism used for sharing memory between Java and native code, and GC may move objects around in memory.
So to utilise this you'd need to create a JNI function which calls the former, then polls a flag written to that critical array (which could just be a byte[1]) waiting till it sees the flag before calling the latter. When the Java code wishes to suspend GC it would call the JNI method and when it wishes to resume GC, set the aforementioned flag (I believe reads/writes to the critical array are volatile, so the native code would see the flag immediately).
Now I'm not saying this is a good idea, and certainly not the correct solution to the OP's problem. But if you absolutely had to temporarily suspend GC for some reason (perhaps you wish to manipulate raw memory via sun.misc.Unsafe and needed to ensure objects were not moved about by GC whilst doing so), that's how you could achieve it.
As everyone as said you can't disable GC in the JVM, which makes sense right, because if you could there'd be memory leaks due to java not having an explicit way for the developer to delete the heap data.
Do you have access to the source of this java binary? If so it might be worth analysing it and seeing if there's any bottle-necks which could be better written to cut down on GC activity. This could be done with most java profilers, like JProbe for example.
To avoid garbage collector release a variable or property from any object,
you must set this property (released by gc) as static in your class
it was my solution.
Example:
private static String myProperty;

What are the best garbage collection settings for client side?

Recent JVM's have a lot of XX parameters for garbage collection (see here for example), but what are the options which can make a client side Swing application really perform better?
I should note that one of the things that really annoys me on client side java applications is the large delay in stop-the-world garbage collection. In Intelli-J IDEA I have seen it go three minutes or more.
EDIT: Thanks for all the responses. Just to report back I put on the CMS garbage collector for IDEA (which is a good common reference of the type of application that most everyone reading this question is familiar with) using the setting's suggested from here. I also set -XX:+StringCache to see if it would reduce memory requirements.
In general, the observation is that regular running performance is not degraded to the point where you can notice looking at it. The memory reduction is huge using the String Cache option, however the CMS method is not thorough and ends up requiring a stop the world garbage collection cycle (back to the three minute wait) to clear out the memory (400MB in one run).
However, given the reduced memory footprint, I might be able to just put a smaller maximum amount of memory which will keep the stop the world collections smaller in sizes.
IDEA 8.1.4 comes with JDK 1.6.0_12, so I didn't test G1 yet. Also, my machine only has 2 cores, so a G1 approach won't really be maximized. Time to hit the boss up for a better machine ;).
There is no single answer to this question, it is highly depending on what your application is doing and how it manages its objects. Maybe have a look at How does garbage collection work and Parallel and concurrent garbage collectors to understand the various options.
Then, check the Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning document that expands on GC tuning concepts and techniques for Java SE 6 that were introduced in the Tuning Garbage Collection with the 5.0 Java Virtual Machine document.
If you want to keep garbage collection pauses short, the concurrent collector is likely the right direction as it performs most of its work concurrently (i.e., while the application is still running). But finding the best setup will require profiling (consider measuring the GC throughput, the max and average pause time, the frequency of full GCs and their duration too).
(EDIT: Having read a comment from the OP, I think that reading My advice on JVM heap tuning, keep your fingers off the knobs! from the performance guru Kirk Pepperdine would be a good idea.)
Garbage collection tuning is more than an art then science, and it really depends on your application and its usage. If the standard stop-the-world strategies bother you, why not convert to the CMS (concurrent mark and sweep) or the new G1 collector?
The best way is to change the parameters and attach a profiler to examine the application behaviour.
This is quite automatic and works for us:
-server -Xss4096k -Xms12G -Xmx12G -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -verbose:gc -Xmaxf1 -XX:+UseCompressedOops -XX:+DisableExplicitGC -XX:+AggressiveOpts -XX:+ScavengeBeforeFullGC -XX:CMSFullGCsBeforeCompaction=10 -XX:CMSInitiatingOccupancyFraction=80 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+CMSIncrementalPacing -XX:+CMSParallelRemarkEnabled -XX:GCTimeRatio=19 -XX:+UseAdaptiveSizePolicy -XX:MaxGCPauseMillis=500 -XX:+PrintGCTaskTimeStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintTenuringDistribution -Xloggc:gc.log
There is no "best" option (if there was, anyone would use it, right?) but maybe an option which helps in your case. But here are some tips:
Use the latest VM. The GC code got better with every release.
Use the client jvm.dll (available sinve Java 1.5 in jre/bin/client/). This should be the default.
Allocating and freeing objects in Java is cheap. It's expensive to keep them around.
If you want better performance then give the garbage collector less work. Consider using a pool of objects rather than constantly creating and dumping them, and make sure you need every object you create.

Categories

Resources