36

Currently in our testing environment the max and min JVM heap size are set to the same value, basically as much as the dedicated server machine will allow for our application. Is this the best configuration for performance or would giving the JVM a range be better?

Clay3981
  • 664
  • 1
  • 5
  • 6
  • 1
    When you set the maximum, it allocates that amount of virtual memory on start up. However, the amount of memory used grows slowly as the heap is used. Even when you specify a minimum size, it doesn't use this space immediately instead it allows the heap to grow to this size quickly. – Peter Lawrey Jul 28 '11 at 18:57

5 Answers5

29

Peter 's answer is correct in that -Xms is allocated at startup and it will grow up to -Xmx (max heap size) but it's a little misleading in how he has worded his answer. (Sorry Peter I know you know this stuff cold).

Setting ms == mx effectively turns off this behavior. While this used to be a good idea in older JVMs, it is no longer the case. Growing and shrinking the heap allows the JVM to adapt to increases in pressure on memory yet reduce pause time by shrinking the heap when memory pressure is reduced. Sometimes this behavior doesn't give you the performance benefits you'd expect and in those cases it's best to set mx == ms. OOME is thrown when heap is more than 98% of time is spent collecting and the collections cannot recover more than 2% of that. If you are not at max heaps size then the JVM will simply grow so that you're beyond that boundaries. You cannot have an OutOfMemoryError on startup unless your heap hits the max heap size and meets the other conditions that define an OutOfMemoryError.

For the comments that have come in since I posted. I don't know what the JMonitor blog entry is showing but this is from the PSYoung collector.

size_t desired_size = MAX2(MIN2(eden_plus_survivors, gen_size_limit()),
                           min_gen_size());

I could do more digging about but I'd bet I'd find code that serves the same purpose in the ParNew and PSOldGen and CMS Tenured implementations. In fact it's unlikely that CMS would be able to return memory unless there has been a Concurrent Mode Failure. In the case of a CMF the serial collector will run and that should include a compaction after which top of heap would most likely be clean and therefore eligible to be deallocated.

Brice
  • 33,480
  • 7
  • 78
  • 93
Kirk
  • 721
  • 7
  • 10
10

Main reason to set the -Xms is for if you need a certain heap on start up. (Prevents OutOfMemoryErrors from happening on start up.) As mentioned above, if you need the startup heap to match the max heap is when you would match it. Otherwise you don't really need it. Just asks the application to take up more memory that it may ultimately need. Watching your memory use over time (profiling) while load testing and using your application should give you a good feel for what to need to set them to. But it isn't the worse thing to set them to the same on start up. For a lot of our apps, I actually start out with something like 128, 256, or 512 for min (startup) and one gigabyte for max (this is for non application server applications).

Just found this question on stack overflow which may also be helpful side-effect-for-increasing-maxpermsize-and-max-heap-size. Worth the look.

Community
  • 1
  • 1
Chris Aldrich
  • 1,866
  • 1
  • 22
  • 37
  • Can you really avoid OOMEs without adjusting the max heap size? I thought the heap would grow up to the maximum size before an OOME, even at startup. I always thought it was there to prevent unnecessary GC cycles and heap resizes if you knew that the program would require some minimum amount of memory anyway. – Mark Peters Jul 29 '11 at 00:47
  • All I can say is that I've had OOME's happen if the min heap size is too low. End up with too many objects on the heap too fast with not enough time to reallocate memory and get a bigger heap, or garbage collect objects. So the main reason for setting Min heap is to assure you have the right space to grow in on JVM/application start up. After that you hopefully have controlled growth that lets you reach the max heap size and/or have good GC. – Chris Aldrich Jul 29 '11 at 13:05
  • You say "with not enough time to reallocate memory and get a bigger heap, or garbage collect". The trouble is, GC can be a blocking operation. The time it takes should be irrelevant. The only thing I can think of is cases where there isn't enough memory available for the OS to give to your process. In that case, starting with a small `Xms` would initialize and then throw an `OOME` whereas starting with a big `Xms` would just fail to initialize the VM, which is hardly better. – Mark Peters Jul 29 '11 at 13:19
  • Probably. I tend to speak from my experience. I learn alot as I go along. So anything I can learn to increase my knowledge is awesome. (part of it is being in a small shop: jack of all trades, master of none). – Chris Aldrich Jul 29 '11 at 14:16
4

AFAIK, setting both to the same size does away with the additional step of heap resizing which might be in your favour if you pretty much know how much heap you are going to use. Also, having a large heap size reduces GC invocations to the point that it happens very few times. In my current project (risk analysis of trades), our risk engines have both Xmx and Xms to the same value which pretty large (around 8Gib). This ensures that even after an entire day of invoking the engines, almost no GC takes place.

Also, I found an interesting discussion here.

Sanjay T. Sharma
  • 21,620
  • 4
  • 54
  • 70
  • Heap resizing is not the same thing as GC invocations. Whenever you create an object, it must (eventually) be collected. So unless your app never instantiates a new object after you've reached your max heap size, you will definitely still be having periodic garbage collections. – Kirk Woll Jul 28 '11 at 17:36
  • Yes, I know that and that's why I mention them separately. – Sanjay T. Sharma Jul 28 '11 at 17:40
2

Definitely yes for a server app. What's the point of having so much memory but not using it? (No it doesn't save electricity if you don't use a memory cell)

JVM loves memory. For a given app, the more memory JVM has, the less GC it performs. The best part is more objects will die young and less will tenure.

Especially during a server startup, the load is even higher than normal. It's brain dead to give server a small memory to work with at this stage.

irreputable
  • 42,827
  • 9
  • 59
  • 89
  • 4
    How much GC is performed has nothing to do with how much heap size there is, it has to do with how many objects are created and freed. Larger heap size will cause less frequent, but bigger and more disruptive garbage collection if using the traditional oracle garbage collection algorithm. So bigger is not better. The exact behavior will depend on the JVM implementation. Further, as discussed in the other answers, ```Xms``` is not a limitation on how much the JVM has at launch. As an aside, language like "brain dead" isn't helpful. – derekv Jul 14 '15 at 18:15
  • In support of this answer there is [this article](https://docs.oracle.com/cd/E21764_01/web.1111/e13814/jvm_tuning.htm) about fine tuning the Weblogic Server, which does say, "Oracle recommends setting the minimum heap size (-Xms) equal to the maximum heap size (-Xmx) to minimize garbage collections." – Max Jul 20 '18 at 13:25
  • @Max: [this article](https://docs.oracle.com/cd/E21764_01/web.1111/e13814/jvm_tuning.htm) mentions "Improving Java Application Performance and Scalability by Reducing Garbage Collection Times and Sizing Memory Using JDK 1.4.1" which must have been outdated in 2018. I am trying to find an updated document as well. – Bart de Kort Apr 21 '21 at 08:43
1

From what I see here at http://java-monitor.com/forum/showthread.php?t=427 the JVM under test begins with the Xms setting, but WILL deallocate memory it doesn't need and it will take it upto the Xmx mark when it needs it.

Unless you need a chunk of memory dedicated for a big memory consumer initially, there's not much of a point in putting in a high Xms=Xmx. Looks like deallocation and allocation occur even with Xms=Xmx

Shock
  • 46
  • 4