We've run into a Java.lang.OutOfMemoryError: PermGen space error and looking at the tomcat JVM params, other than the -Xms and -Xmx params we also specify -XX:MaxPermSize=128m. After a bit of profiling I can see occasionally garbage collection happening on the PermGen space saving it from running full.
My question is: other than increasing the -XX:MaxPermSize what would be the difference if I specify as well -XX:PermSize? I know the total memory then would be Xmx+maxPermSize but is there any other reason why -XX:PermSize should not be there when -XX:MaxPermSize is specified?
Please do share if you have real-world experience dealing with these JVM parameters.
ps. The JVM is HotSpot 64bit Server VM build 16.2-b04
-XX:PermSize specifies the initial size that will be allocated during startup of the JVM. If necessary, the JVM will allocate up to -XX:MaxPermSize.
By playing with parameters as -XX:PermSize and -Xms you can tune the performance of - for example - the startup of your application. I haven't looked at it recently, but a few years back the default value of -Xms was something like 32MB (I think), if your application required a lot more than that it would trigger a number of cycles of fill memory - full garbage collect - increase memory etc until it had loaded everything it needed. This cycle can be detrimental for startup performance, so immediately assigning the number required could improve startup.
A similar cycle is applied to the permanent generation. So tuning these parameters can improve startup (amongst others).
WARNING The JVM has a lot of optimization and intelligence when it comes to allocating memory, dividing eden space and older generations etc, so don't do things like making -Xms equal to -Xmx or -XX:PermSize equal to -XX:MaxPermSize as it will remove some of the optimizations the JVM can apply to its allocation strategies and therefor reduce your application performance instead of improving it.
As always: make non-trivial measurements to prove your changes actually improve performance overall (for example improving startup time could be disastrous for performance during use of the application)
If you're doing some performance tuning it's often recommended to set both -XX:PermSize and -XX:MaxPermSize to the same value to increase JVM efficiency.
Here is some information:
Support for large page heap on x86 and amd64 platforms
Java Support for Large Memory Pages
Setting the Permanent Generation Size
You can also specify -XX:+CMSClassUnloadingEnabled to enable class unloading
option if you are using CMS GC. It may help to decrease the probability of Java.lang.OutOfMemoryError: PermGen space
Related
I have an application that can be executed when I use the jvm command -Xmx65m. Although it is running fine, I want to allow the application to consume more memory, because it has some features that require it. The problem is that if I increase the -Xmx option, the JVM will alocate more memory to run the features that it can handle with only 65 MB.
Is it possible to configure the JVM to only request more memory to the SO only when it is running out of options and it is about to throw an OutOfMemoryError?
Please add the min , max memory settings. So that JVM can start with the min required memory and keeps allocating more memory as and when its required.
-Xms65m -Xmx512m
Hope this helps.
The JVM reserves the maximum heap size as virtual memory on start up but it only uses the amount it needs (even if you set a minimum size it might not use that much) If it uses a large amount of memory but doesn't need it any more it can give back to the OS (but often doesn't AFAIK)
Perhaps you are not seeing a gradual increase as your maximum is so small. Try it with a maximum of -mx1g and look in jvisualvm as to how the maximum heap size grows.
Is it possible to configure the JVM to only request more memory to the SO only when it is running out of options and it is about to throw an OutOfMemoryError?
As the JVM gets close to finally running out of space, it runs the GC more and more frequently, and application throughput (in terms of useful work done per CPU second) falls dramatically. You don't want that happening if you can avoid it.
There is one GC tuning option that you could use to discourage the JVM from growing the heap. The -XX:MinHeapFreeRatio option sets the "minimum percentage of heap free after GC to avoid expansion". If you reduce this from the default value of 40% to (say) 20% the GC will be less eager to expand the heap.
The down-side is that if you reduce -XX:MinHeapFreeRatio, the JVM as a whole will spend a larger percentage of its time running the garbage collector. Go too far and the effect could possibly be quite severe. (Personally, I would not recommend changing this setting at all ... )
I have a jvm server in my machine, now I want to have 2 apservers of mine sitting in same machine, however I want the standby one to have a really low amount of memory allocated with xmx because its passive, one the main server (active) goes down I want to allocate more memory to my passive server which is already up without restarting it (I have have them both having too much xmx - note they would consume memory at startup and I cant allow possibility of outOfMemory).
So I want passive - low xmx
once active goes down I want my passive to receive much more xmx.
is there a way for me to achieve that.
Thanks
It would be nice, but as far as I know it's not an option with the Sun provided JVMs.
The Xmx option is to specify maximum memory, it's there to prevent the JVM from consuming the entire machine's free memory. If you want to set it higher, it won't require the JVM allocate all of that memory. Why not just set it to a very high number and let the JVM grow into it over time?
To make sure your JVM doesn't start off with too little memory (creating lots of pauses as it grows the memory to the required size), adjust Xms to the size you want to allocate for the JVM at startup.
The short answer is unless your particular JVM allows for these values to be changed after initialization, you cannot (I believe this is the case for HotSpot).
However, you may be able to accomplish your goals without changing Xmx on the fly. For example, you could use a small -Xms setting, but keep -Xmx relatively high. If the passive server is not using much memory / generating garbage while still serving as the backup, then memory will stay near the Xms value. However, once the backup server takes over it would be allowed to expand allocated memory up to the Xmx value on an as-needed basis.
See java (windows) or java (*nix) as appropriate (though -Xms and -Xmx have the same general meaning on all platforms).
You don't need to adjust Xmx on the standby instance as long as it's not doing anything (or much of anything) because it should stay close to the value you set with Xms until it starts doing real work.
The Xmx switch governs the maximum amount of heap size the Java instance may consume. Xms governs the startup amount.
If you set Xms small on your standby instance and Xmx to whatever maximum your program needs, and then switch over to the Standby instance (killing the regular instance) it should work out fine.
It may be necessary to actually stop/kill the regular Java process depending on your available memory in order for the standby process to allocate all of the heap it needs as it moves from the initial lower heap size to toward it's maximum.
For the JVM to fill all the heap, you'd have to generate enough objects that survive the young generation collection. That would be unlikely on the lightly-loaded stand-by server.
To improve your chances of catching all the garbage in the young generation, configure your young generation heap accordingly: larger sizes, more generations before objects age out. This is a compromise between confining your standby server to young generation and the collection profile you need in your primary server.
Update: the new G1 collector uses different configuration options. PLease look at http://www.oracle.com/technetwork/tutorials/tutorials-1876574.html to learn more. The option most relevant to your case would be
-XX:InitiatingHeapOccupancyPercent=45 - Percentage of the (entire) heap occupancy to start a concurrent GC cycle. It is used by G1 to trigger a concurrent GC cycle based on the occupancy of the entire heap, not just one of the generations. A value of 0 denotes 'do constant GC cycles'. The default value is 45 (i.e., 45% full or occupied).
IOW, the equivalent of young generation collection will start when the current heap (the min heap size initially) is 45% used up. Your light-load server should never leave the min heap size (unless it produces relatively long-living objects, in which case see -XX:MaxTenuringThreshold).
What is the benefit of setting the -Xms parameter, and having the initial memory larger for example, then the default calculated one (64 MB in my case, according to Java GC tunning:
http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html#par_gc.ergonomics.default_size)?
Also, is there any good to setting both the initial and maximum memories to same size?
Thanks.
The benefit is that there is a performance penalty when you use up enough of the heap that it has to be resized. If you set it initially to 64MB but it turns out your application under load needs 250MB, when you hit near 64MB the JVM will allocate more heap space and possibly move around some objects and do other book-keeping. This of course takes time.
When your application is under load, you want all resources dedicated to making it run, so this extra work can make the application slower to respond, or even in some instances it can crash if it runs out of memory before the heap is resized.
Sometimes when using a Java app, you'll see instructions like "set Xms and Xmx to the same value". This is done to avoid the resizing altogether, so that your application launches with its heap already as big as it will ever be.
The linked article explains it clear enough:
Default values: -Xms 3670k
-Xmx 64m
[...]
Large
server applications often experience
two problems with these defaults. One
is slow startup, because the initial
heap is small and must be resized over
many major collections. A more
pressing problem is that the default
maximum heap size is unreasonably
small for most server applications.
The rules of thumb for server
applications are:
Unless you have problems with
pauses, try granting as much memory
as possible to the virtual machine.
The default size (64MB) is often too
small.
Setting -Xms and -Xmx to the
same value increases predictability
by removing the most important
sizing decision from the virtual
machine. However, the virtual
machine is then unable to compensate
if you make a poor choice.
In general, increase the memory as you
increase the number of processors,
since allocation can be
parallelized.
You can also be interested in this discussion of the problem.
What is the benefit of setting the -Xms parameter, and having the initial memory larger for example, then the default calculated one
If the initial heap is small and must be resized over many major collections, the startup will be slow.
Also, is there any good to setting both the initial and maximum memories to same size?
Setting -Xms and -Xmx to the same value gives you predictability. This is especially important when sizing the JVM during performance tuning. But the JVM won't be able to compensate any bad decision.
I tend to use the same values for production servers (which are tuned during performance testing).
If it is normal for your application to require more than 64 MB of heap memory, setting Xms to a larger value should improve the application's performance somewhat because the VM would not have to request additional memory as many times.
In a production system I consider setting Xms and Xmx to the same value sensible. It's basically saying "this is the amount of heap memory the VM can get and I'm dedicating it right away".
Given these two commands
A:
$ java -Xms10G -Xmx10G myjavacode input.txt
B:
$ java -Xms5G -Xmx5G myjavacode input.txt
I have two questions:
Since command A reserves more memory with its parameters, will A run faster than B?
How do -Xmx and -Xms affect the running process and the output of my program?
The -Xmx argument defines the max memory size that the heap can reach for the JVM. You must know your program well and see how it performs under load and set this parameter accordingly. A low value can cause OutOfMemoryExceptions or a very poor performance if your program's heap memory is reaching the maximum heap size. If your program is running in dedicated server you can set this parameter higher because it wont affect other programs.
The -Xms argument sets the initial heap memory size for the JVM. This means that when you start your program the JVM will allocate this amount of memory instantly. This is useful if your program will consume a large amount of heap memory right from the start. This avoids the JVM to be constantly increasing the heap and can gain some performance there. If you don't know if this parameter is going to help you, don't use it.
In summary, this is a compromise that you have to decide based only in the memory behavior of your program.
It depends on the GC your java is using. Parallel GCs might work better on larger memory settings - I'm no expert on that though.
In general, if you have larger memory the less frequent it needs to be GC-ed - there is lots of room for garbage. However, when it comes to a GC, the GC has to work on more memory - which in turn might be slower.
I have found that in some cases too much memory can slow the program down.
For example I had a hibernate based transform engine that started running slowly as the load increased. It turned out that each time we got an object from the db, hibernate was checking memory for objects that would never be used again.
The solution was to evict the old objects from the session.
Stuart
Allocation always depends on your OS. If you allocate too much memory, you could end up having loaded portions into swap, which indeed is slow.
Whether your program runs slower or faster depends on the references the VM has to handle and to clean. The GC doesn't have to sweep through the allocated memory to find abandoned objects. It knows it's objects and the amount of memory they allocate by reference mapping. So sweeping just depends on the size of your objects. If your program behaves the same in both cases, the only performance impact should be on VM startup, when the VM tries to allocate memory provided by your OS and if you use the swap (which again leads to 1.)
The speed tradeoffs between various settings of -Xms and -Xmx depend on the application and system that you run your Java application on. It also depends on your JVM and other garbage collection parameters you use.
This question is 11 years old, and since then the effects of the JVM parameters on performance have become even harder to predict in advance. So you can try different values and see the effects on performance, or use a free tool like Optimizer Studio that will find the optimal JVM parameter values automatically.
It is difficult to say how the memory allocation will affect your speed. It depends on the garbage collection algorithm the JVM is using. For example if your garbage collector needs to pause to do a full collection, then if you have 10 more memory than you really need then the collector will have 10 more garbage to clean up.
If you are using java 6 you can use the jconsole (in the bin directory of the jdk) to attach to your process and watch how the collector is behaving. In general the collectors are very smart and you won't need to do any tuning, but if you have a need there are numerous options you have use to further tune the collection process.
> C:\java -X
-Xmixed mixed mode execution (default)
-Xint interpreted mode execution only
-Xbootclasspath:<directories and zip/jar files separated by ;>
set search path for bootstrap classes and resources
-Xbootclasspath/a:<directories and zip/jar files separated by ;>
append to end of bootstrap class path
-Xbootclasspath/p:<directories and zip/jar files separated by ;>
prepend in front of bootstrap class path
-Xnoclassgc disable class garbage collection
-Xincgc enable incremental garbage collection
-Xloggc:<file> log GC status to a file with time stamps
-Xbatch disable background compilation
-Xms<size> set initial Java heap size
-Xmx<size> set maximum Java heap size
-Xss<size> set java thread stack size
-Xprof output cpu profiling data
-Xfuture enable strictest checks, anticipating future default
-Xrs reduce use of OS signals by Java/VM (see documentation)
-Xcheck:jni perform additional checks for JNI functions
-Xshare:off do not attempt to use shared class data
-Xshare:auto use shared class data if possible (default)
-Xshare:on require using shared class data, otherwise fail.
The -X options are non-standard and subject to change without notice.
(copy-paste)
This was always the question I had when I was working on one of my application which created massive number of threads per request.
So this is a really good question and there are two aspects of this:
1. Whether my Xms and Xmx value should be same
- Most websites and even oracle docs suggest it to be the same. However, I suggest to have some 10-20% of buffer between those values to give heap resizing an option to your application in case sudden high traffic spikes OR a incidental memory leak.
2. Whether I should start my Application with lower heap size
- So here's the thing - no matter what GC Algo you use (even G1), large heap always has some trade off. The goal is to identify the behavior of your application to what heap size you can allow your GC pauses in terms of latency and throughput.
- For example, if your application has lot of threads (each thread has 1 MB stack in native memory and not in heap) but does not occupy heavy object space, then I suggest have a lower value of Xms.
- If your application creates lot of objects with increasing number of threads, then identify to what value of Xms you can set to tolerate those STW pauses. This means identify the max response time of your incoming requests you can tolerate and according tune the minimum heap size.
Does the Sun JVM slow down when more memory is available and used via -Xmx? (Assumption: The machine has enough physical memory so that virtual memory swapping is not a problem.)
I ask because my production servers are to receive a memory upgrade. I'd like to bump up the -Xmx value to something decadent. The idea is to prevent any heap space exhaustion failures due to my own programming errors that occur from time to time. Rare events, but they could be avoided with my rapidly evolving webapp if I had an obscene -Xmx value, like 2048mb or higher. The application is heavily monitored, so unusual spikes in JVM memory consumption would be noticed and any flaws fixed.
Possible important details:
Java 6 (runnign in 64-bit mode)
4-core Xeon
RHEL4 64-bit
Spring, Hibernate
High disk and network IO
EDIT: I tried to avoid posting the configuration of my JVM, but clearly that makes the question ridiculously open ended. So, here we go with relevant configuration parameters:
-Xms256m
-Xmx1024m
-XX:+UseConcMarkSweepGC
-XX:+AlwaysActAsServerClassMachine
-XX:MaxGCPauseMillis=1000
-XX:MaxGCMinorPauseMillis=1000
-XX:+PrintGCTimeStamps
-XX:+HeapDumpOnOutOfMemoryError
By adding more memory, it will take longer for the heap to fill up. Consequently, it will reduce the frequency of garbage collections. However, depending on how mortal your objects are, you may find that how long it takes to do any single GC increases.
The primary factor for how long a GC takes is how many live objects there are. Thus, if virtually all of your objects die young and once you get established, none of them escape the young heap, you may not notice much of a change in how long it takes to do a GC. However, whenever you have to cycle the tenured heap, you may find everything halting for an unreasonable amount of time since most of these objects will still be around. Tune the sizes accordingly.
If you just throw more memory at the problem, you will have better throughput in your application, but your responsiveness can go down if you're not on a multi core system using the CMS garbage collector. This is because fewer GCs will occur, but they will have more work to do. The upside is that you will get more memory freed up with your GCs, so allocation will continue to be very cheap, hence the higher througput.
You seem to be confusing -Xmx and -Xms, by the way. -Xms just sets the initial heap size, whereas -Xmx is your max heap size.
More memory usually gives you better performance in garbage collected environments, at least as long as this does not lead to virtual memory usage / swapping.
The GC only tracks references, not memory per se. In the end, the VM will allocate the same number of (mostly short-lived, temporary) objects, but the garbage collector needs to be invoked less often - the total amount of garbage collector work will therefore not be more - even less, since this can also help with caching mechanisms which use weak references.
I'm not sure if there is still a server and a client VM for 64 bit (there is for 32 bit), so you may want to investigate that also.
According to my experience, it does not slow down BUT the JVM tries to cut back to Xms all the time and try to stay at the lower boundary or close to. So if you can effort it, bump Xms as well. Sun is recommending both at the same size. Add some -XX:NewSize=512m (just a made up number) to avoid the costly pile up of old data in the old generation with leads to longer/heavier GCs on the way. We are running our web app with 700 MB NewSize because most data is short-lived.
So, bottom line: I do not expect a slow down, but put your more of memory to work. Set a larger new size area and set Xms to Xmx to lower the stress on the GC, because it does not need to try to cut back to Xms limits...
It typically will not help your peformance/throughput,if you increase -Xmx.
Theoretically there could be longer "stop the world" phases but in practice with the CMS that's not a real problem.
Of course you should not set -Xmx to some insane value like 300Gbyte unless you really need it :)