Wildfly 16 : What is benefit of changing XX:MaxMetaspaceSize in Java8? - java-8

I am getting metaspace issue in Wildfly.
Currently XX:MaxMetaspaceSize is 256M. But i am getting following issue multiple times in multiple server groups in different projects (50 projects in total distributed among server groups). And facing following exception daily.
failed to define class: OutOfMemoryException: Metaspace
Most of posts(stackoverflow and others) suggest it should be 2GB in case of wildfly.
But i have read in various article which suggests that in Java 8 there is no need to increasing Metaspace:
In Java 8, the metaspace that holds your classes can expand without limit by default,
Could you please resolve this confusion that - if Metaspace is automatically increased and suppose i have set 256 then does it not automatically increase? What benefit i will get at 2G.

Per the Oracle docs, in Java 8, the class metadata is stored in native memory and by default is unlimited. MaxMetaspaceSize puts an upper limit on the native memory that's used for class metadata.
If you also have UseCompressedOops and UseCompressedClassesPointers enabled, then MaxMetaspaceSize sets the upper limit on the sum of both areas of native memory used for class metadata - the area for the compressed class metadata, and the area for all other class metadata.
Also, 2GB sounds a bit high. I would slowly increase and test to be sure you're setting this to an optimal value for your needs.

Related

Recommended Java Heap Size for Commercial JMeter Project

Depending on the nature of the automated workflow and the number of active threads at any given time the Heap size requirement for JMeter can vary and in the testing I am doing there is some ambiguity with respect to the affect of Heap size on the test results. The initial Heap size and the maximum Heap size of the server hosting JMeter is shown in the attached screenshot.
Upon executing the test for a large set of current users (eg:100) the in built JMeter report does not render however the results can be seen in the CSV output. Will increasing the Heap size solve this issue and if so to how much should we increase the Heap size?. Note that this issue does not happen for a small user count such as 10 or 15.
What is the recommended industrial standard value for Heap size and other system variables for a server used for commercial performance testing using JMeter.
There is no "recommended industrial standard".
Each test is individual and you need to tune JMeter appropriately.
As of JMeter 5.5 default heap size is 1GB which is sufficient for tests development and debugging but might be not sufficient for the load you're trying to conduct.
According to this article:
"If the occupancy of the Java heap is too high, garbage collection occurs frequently. If the occupancy is low, garbage collection is infrequent but lasts longer... Try to keep the memory occupancy of the Java heap between 40% and 70% of the Java heap size... The highest point of occupancy of the Java heap is preferably not above 70% of the maximum heap size, and the average occupancy is between 40% and 70% occupancy. If the occupancy goes over 70%, resize the Java heap."
So I would recommend checking what's going on with your heap using JVisualVM or equivalent and adjusting it up or down as needed.
If your test runs fine and you're experiencing OOM issues only during dashboard generation you can increase it temporarily by setting the relevant HEAP environment variable value.

Java buildpack memory calculation

Java buildpack memory calculator with Spring Boot application inside of Docker container with 1GB memory calculates memory as it says in documentation, it takes entire available memory and this are calculated JVM options:
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -Xmx747490K -XX:MaxMetaspaceSize=157725K -Xss1M (Total Memory: 1G, Thread Count: 50, Loaded Class Count: 25433, Headroom: 0%)
Question is why does it takes entire available memory and gives it to JVM? It should leave some memory for java process outside of JVM. This can lead to OOM because JVM thinks it has 1GB for itself (747490K for heap), and in reality it has less because some of it's memory is used by native memory, outside of JVM.
Should I not use this calculator and set JVM configuration by myself or I can reconfigure this somehow?
Question is why does it takes entire available memory and gives it to JVM?
The assumption is that the only thing running in your container is your Java application, thus it assigns all of the available memory to be used.
If you do things like shell out and run other processes or run other processes in the container, you need to tell memory calculator so it can take that into account.
This can lead to OOM because JVM thinks it has 1GB for itself (747490K for heap), and in reality it has less because some of it's memory is used by native memory, outside of JVM.
The memory calculator takes into consideration the major memory regions within a Java process. Not just heap. That said, it cannot 100% guarantee that you will never go over your memory limit. That's impossible with a Java app.
There are things you can do as an application developer, like create 10,000 threads or JNI, that cannot be restricted and could potentially consume a whole ton of memory. If you do that, your app will go over its container memory limit and crash.
The memory calculator attempts to give you a reasonable memory configuration for most common Java workloads. Running a web app, running a microservice, running some batch jobs, etc...
If you are doing something that doesn't fit within that pattern, then you can simply tell the memory calculator and it'll adjust things accordingly.
Should I not use this calculator and set JVM configuration by myself or I can reconfigure this somehow?
Even if you need to customize what the calculator is doing it can be helpful. It's additional toil to calculate these values manually, especially when it's so easy to change the memory limits. If your ops team increases the memory limit of the container, you want your application to automatically adjust to that configuration (as well as it can).
Beyond that, memory calculator is also good at detecting problems early. If you configure the JVM manually and you mess it up, let's say you over-allocate memory, the JVM won't necessarily care until it tries to get more memory and can't. At some point down the road, you're going to have a problem but it's not clear when (probably at 3am on a Sat, lol).
With memory calculator, it's doing the math when your container first starts to make sure that memory settings are sane. If there's something off with the configuration, it'll fail and let you know.
TIPS:
You can override a memory calculator-defined value by simply setting that JVM option in the JAVA_TOOL_OPTIONS env variable. For example, if I want to allow for more direct memory, I would set JAVA_TOOL_OPTIONS='-XX:MaxDirectMemorySize=50M'. Then when you restart the container, the memory calculator will shift memory around to accommodate that.
The one thing you don't want to set is -Xmx. The memory calculator should always set this because it will set it to whatever is left after other regions have been accounted for. You can think of it like HEAP = CONTAINER_MEMORY_LIMIT - (all static memory regions).
If you were to set -Xmx, you have to get it exactly right. If it's too low then you're wasting memory. If it's too high then you could exceed the container memory limit and get crashes.
In short, if you think you want to set -Xmx, you should either increase the container memory limit or decrease one of the static memory regions.
If you run other things in the container, you need to set the headroom. This is done with the BPL_JVM_HEAD_ROOM env variable. Give it a percent of the total container memory limit. Ex: BPL_JVM_HEAD_ROOM=20 would use 80% of the container's memory limit for Java and 20 for other stuff.
Setting some headroom can be useful in other cases as well, like if you're troubleshooting a container crash and you want a little extra room, or if you don't like operating at 100% the memory limit. You can leave 5 or 10% unused to match your comfort level.
If you have an application that uses a lot of threads, you'll need to adjust this as well. The default is 250 threads, which works well for many web/servlet-based applications (thread per request model). We do automatically lower to 50 threads if you're specifically using Spring Webflux which does not need so many threads.
For other cases, it's up to you to configure this. For example, if you have a batch application that only needs a thread pool of 10, then you could set this 40 or 50. 40-50 seems weird in this example, but the JVM creates a number of its own threads and you need to account for those in addition to application-specific threads when in doubt look at a thread dump.

Garbage collection tuning for Java 8 Applications

1) Our application: Spring boot, Java 8
2) Parameters we use: xms = 256 MB, xmx = 2 GB
We have been seeing that used heap size of our java8 applications are not shrinking back down when appropriate.
Any other parameters that we should be using along with #2 above, when launching our spring boot/Java 8 application, so that GC can do a better job?
Thanks for your help!
The above options have the following effect:
-Xms, -Xmx: Places boundaries on the heap size to increase the predictability of garbage collection. The heap size is limited in replica servers so that even Full GCs do not trigger SIP retransmissions. -Xms sets the starting size to prevent pauses caused by heap expansion.
-XX:+UseG1GC: Use the Garbage First (G1) Collector.
-XX:MaxGCPauseMillis: Sets a target for the maximum GC pause time. This is a soft goal, and the JVM will make its best effort to achieve it.
-XX:ParallelGCThreads: Sets the number of threads used during parallel phases of the garbage collectors. The default value varies with the platform on which the JVM is running.
-XX:ConcGCThreads: Number of threads concurrent garbage collectors will use. The default value varies with the platform on which the JVM is running.
-XX:InitiatingHeapOccupancyPercent: Percentage of the (entire) heap occupancy to start a concurrent GC cycle. GCs that trigger a concurrent GC cycle based on the occupancy of the entire heap and not just one of the generations, including G1, use this option. A value of 0 denotes 'do constant GC cycles'. The default value is 45.
Oracle JDK provides inbuilt Java VisualIVM tool to analyze and tune GC factors

Find my application memory foot print programmatically

I am trying to measure my application memory foot print pragmatically.
I am using java.lang.management class to calculate this
val heap = ManagementFactory.getMemoryMXBean.getHeapMemoryUsage
val nonHeap = ManagementFactory.getMemoryMXBean.getNonHeapMemoryUsage
val total = heap + nonHeap + (?)
I assumed the sum of both will give me the total amount of memory used by application, but this is not the case, the actual size is greater which was provided by top command.
So I am trying to understand what am I missing? What else do I need to add to this equation in order to get the total memory usage of my application.
To find the memory usage as provided by top, check the OS-level statistics for the process.
On Linux you can do this by reading /proc/self/stat or /proc/self/status.
More about proc pseudo-file system.
Note that Application footprint is a different concept. From JVM point of view
Java application footprint is roughly the amount of space occupied by Java objects (Heap)
and Java classes (Non-heap). From OS point of view there are much more things to count,
including JVM itself and all the components of Java Runtime that make your application work.
The memory used by the whole Java process include
Java Heap;
Metaspace (for class metadata);
Code Cache (the place for JIT-compiled methods and all the generated code);
Direct ByteBuffers;
Memory-mapped files, including files mapped by JVM, e.g. all JAR files on the classpath;
Thread stacks;
JVM code itself and all the dynamic libraries loaded by Java Runtime;
Many other internal JVM structures.

Stanford NER - Heap space error

I am using Stanford NER in my web application and english.muc.7class.distsim.crf.ser.gz (16 MB size)as a classifier.When I try to deploy and run my application am getting a heap space - Out of Memory error while loading the classifier.
Have tried keeping the useful code only also checked if the code is not creating too many objects and occupying the space. But no success.
Is it because of the size of the classifier? But i want to use the same so what should I do?
Have increased the heap size on local using vm options in tomcat.But I can increase the heap size of vm on the actual server where I will host my application and that's not the right way either.
Can anyone guide me about this?
Yes, you basically shouldn't worry much about the size of the code, since it is dominated by the size of the data loaded.
Model data: The classifier models just take a lot of space. It seems like you need a heap of about 140 MB to load the current (2012) version of english.muc.7class.distsim.crf.ser.gz . They're just a lot of Strings and doubles, but there's a big increase from the size on disk because: the on disk data is compressed, as is well known, String objects in java each take a huge amount of space, and they're linked via a HashMap which takes more space. It seems like the String data alone ends up taking about 72 MB in memory (36 MB of char[] data, 36 MB of String objects).
Data to be analyzed: This depends on how you're calling it and may not be a problem in your case with tomcat, but if NER is run on a file, it will read the whole file into memory before classifying. So you can reduce memory by giving it multiple smaller units (files, Strings, or whatever) to classify.
Also, you're much more likely to get prompt help on questions like this with the tag stanford-nlp.
I agree with Christopher suggestions, you don't worry about the size.
But for robust performance try to use Java thread that is live for ever and load the classifier only once at the start of serevr via static method or some listener. Then for further annotation use the same context.

Resources