Why Default Linux Limits Fail Under Load
Section titled “Why Default Linux Limits Fail Under Load”Linux out-of-the-box is configured for balanced desktop and general-purpose server workloads. High-volume load generators stress the TCP stack and operating system kernel in distinct ways:
1. File Descriptor Limits (Too many open files)
Section titled “1. File Descriptor Limits (Too many open files)”Every outbound TCP socket connection, active JTL results writer, and loaded JAR library consumes a file descriptor.
- Default limit:
ulimit -nis typically1024on standard distributions. - Under load: A test running 2,000 threads opening connections simultaneously will crash with
java.io.IOException: Too many open files. - Solution: Set
nofileto524,288or1,048,576inlimits.confandsystemdmanager configs.
2. Ephemeral Port Exhaustion (BindException: Address already in use)
Section titled “2. Ephemeral Port Exhaustion (BindException: Address already in use)”When JMeter opens outbound HTTP/1.1 connections without keep-alive or with rapid connection cycling, closed sockets sit in the TIME_WAIT state for 60 seconds to ensure lingering network packets are drained.
- Default range:
net.ipv4.ip_local_port_rangedefaults to32768 60999(~28,231 ports). - Under load: Generating 1,000 new connections per second exhausts all 28k ports in less than 30 seconds, throwing
java.net.BindException: Address already in use. - Solution: Expand the range to
1024 65535(64,512 ports), enablenet.ipv4.tcp_tw_reuse = 1, and reducenet.ipv4.tcp_fin_timeout = 15.
[!WARNING] Never enable
net.ipv4.tcp_tw_recycle: This legacy parameter was deprecated in Linux 4.10 and removed in 4.12 because it dropped valid SYN packets from clients or load injectors operating behind NAT / load balancers. Always usenet.ipv4.tcp_tw_reuse = 1instead.
3. SYN & Listen Queue Backlog Overflows
Section titled “3. SYN & Listen Queue Backlog Overflows”During rapid test ramp-up or surge testing, connection requests queue up in the kernel socket listen queue.
- Default backlog:
net.core.somaxconndefaults to128or1024. - Under load: Bursts overflow the queue, causing silent SYN drops and artificial connection timeouts.
- Solution: Increase
net.core.somaxconn = 65535andnet.ipv4.tcp_max_syn_backlog = 65535.
4. Swapping Protection (vm.swappiness = 1)
Section titled “4. Swapping Protection (vm.swappiness = 1)”The Linux kernel aggressively pages memory to swap space when RAM usage increases.
- Default swappiness:
60(very prone to paging). - Under load: If inactive JVM heap memory is paged out to disk, the next Garbage Collection cycle must read pages back from storage, freezing threads and creating catastrophic 100ms–2000ms latency spikes.
- Solution: Set
vm.swappiness = 1to ensure the kernel only swaps under critical out-of-memory emergency pressure.
How to Apply These Settings
Section titled “How to Apply These Settings”1. Apply Sysctl Kernel Parameters
Section titled “1. Apply Sysctl Kernel Parameters”Create a dedicated file in /etc/sysctl.d/:
sudo nano /etc/sysctl.d/99-jmeter-tuning.conf# Paste the generated sysctl.conf snippetsudo sysctl --system2. Apply File Descriptor Limits
Section titled “2. Apply File Descriptor Limits”Place user limits in /etc/security/limits.d/:
sudo nano /etc/security/limits.d/99-jmeter.conf# Paste the generated limits.conf snippet[!NOTE] For
limits.confchanges to take effect on interactive sessions, log out and log back in, then verify withulimit -n. For background services managed by systemd, configureDefaultLimitNOFILEin/etc/systemd/system.confand reload systemd withsudo systemctl daemon-reexec.
3. Verify Active Settings
Section titled “3. Verify Active Settings”Run this quick diagnostic to confirm your kernel accepted the values:
ulimit -nsysctl net.ipv4.ip_local_port_range net.ipv4.tcp_tw_reuse net.core.somaxconn vm.swappinessss -s