Skip to content

JMeter JVM, Memory & Operating System Tuning

Scale JMeter injectors for high throughput: JVM heap sizing, G1GC tuning, headless CLI optimization, and Linux kernel TCP/socket configuration.

Difficulty
advanced
Guide type
how-to
Estimated read time
14 min read
Last verified version
Verified JMeter 5.6

JMeter JVM, Memory & Operating System Tuning

Section titled “JMeter JVM, Memory & Operating System Tuning”

When running high-volume performance tests (thousands of virtual users or tens of thousands of requests per second), the bottleneck is frequently the load generator itself rather than the target application. Un-tuned JMeter injectors suffer from heap exhaustion (OutOfMemoryError), excessive Garbage Collection (GC) pauses, port exhaustion, and CPU throttling.

This guide provides end-to-end instructions for tuning JMeter’s JVM heap, Garbage Collector, operating system TCP parameters, and test plan efficiency.


1. JVM Heap Sizing (setenv.sh / setenv.bat)

Section titled “1. JVM Heap Sizing (setenv.sh / setenv.bat)”

By default, Apache JMeter ships with a conservative heap allocation (often 1 GB). For production load generation, allocate 50% to 70% of available system RAM to the JVM heap.

Create a setenv.sh (Linux/macOS) or setenv.bat (Windows) file in JMeter’s bin/ directory:

#!/bin/sh
# Allocate 8GB min and max heap with G1GC
export HEAP="-Xms8g -Xmx8g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m"
export GC_ALGO="-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1ReservePercent=15"
export JVM_ARGS="-XX:+AlwaysPreTouch -Djava.awt.headless=true"
Terminal window
@echo off
set HEAP=-Xms8g -Xmx8g -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
set GC_ALGO=-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:G1ReservePercent=15
set JVM_ARGS=-XX:+AlwaysPreTouch -Djava.awt.headless=true

Use the G1 Garbage Collector (default on modern Java versions). Key flags:

  • -XX:+UseG1GC: Low-latency concurrent collector optimized for multi-gigabyte heaps.
  • -XX:MaxGCPauseMillis=100: Target maximum pause time goal.
  • -XX:InitiatingHeapOccupancyPercent=45: Initiates concurrent marking before memory gets dangerously full.
  • -XX:G1ReservePercent=15: Prevents allocation failures during concurrent cycles.

To log garbage collection events for analysis:

Terminal window
-Xlog:gc*,gc+phases=debug:file=jmeter_gc.log:time,uptime,pid:filecount=5,filesize=50M

3. Operating System & Kernel TCP Tuning (Linux)

Section titled “3. Operating System & Kernel TCP Tuning (Linux)”

Under high RPS, JMeter opens and closes thousands of TCP sockets per minute. Without kernel tuning, you will encounter java.net.BindException: Address already in use or Too many open files.

A. Increase File Descriptor Limits (/etc/security/limits.conf)

Section titled “A. Increase File Descriptor Limits (/etc/security/limits.conf)”
* soft nofile 655350
* hard nofile 655350
* soft nproc 655350
* hard nproc 655350

B. Optimize TCP Sockets in /etc/sysctl.conf

Section titled “B. Optimize TCP Sockets in /etc/sysctl.conf”

Apply with sudo sysctl -p:

# Enable fast recycling of TIME_WAIT sockets
net.ipv4.tcp_tw_reuse = 1
# Expand ephemeral port range
net.ipv4.ip_local_port_range = 1024 65535
# Reduce TIME_WAIT timeout to 30 seconds
net.ipv4.tcp_fin_timeout = 15
# Increase network connection backlog queue
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.core.netdev_max_backlog = 100000
# Increase socket memory buffers
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

4. Test Plan & Execution Architecture Best Practices

Section titled “4. Test Plan & Execution Architecture Best Practices”
Anti-Pattern (High Overhead)Tuned Best Practice (Maximum Throughput)
Running test via GUIAlways use CLI (jmeter -n -t plan.jmx)
Active View Results Tree or Summary ReportDisable all GUI listeners during load runs
Saving full response data in JTL logSave only minimal CSV metrics (jmeter.save.saveservice.*)
BeanShell / JavaScript scriptsJSR223 Groovy with “Cache compiled script” checked
Dynamic \${var} inside cached scriptsvars.get("var") inside script body
Heavy DOM XPath extractorsBoundary Extractor or JSON Extractor

By default, Java caches DNS lookups forever. If load testing microservices behind an AWS ALB or round-robin DNS:

  1. In system.properties, set DNS cache TTL:
networkaddress.cache.ttl=10
networkaddress.cache.negative.ttl=0
  1. In HTTP Request Defaults, check Use MD5 checksum only if verifying large file download integrity.
On this page