Backend Development 11 min read

Measuring Per‑Request Heap Memory Usage in SpringBoot with JMeter

This article describes an experiment using SpringBoot 2.5.4 and JMeter to measure the heap memory allocated per HTTP and RPC request, detailing the setup, GC logging configuration, results showing average memory consumption around 34 KB per request, and recommendations for logging and performance optimization.

Top Architect
Top Architect
Top Architect
Measuring Per‑Request Heap Memory Usage in SpringBoot with JMeter

In this technical note a senior architect explains how to conduct a full‑link stress test, tune GC parameters, and calculate the heap memory required for a single RPC or HTTP request in a SpringBoot application.

1. Experiment Idea

The goal is to determine how much heap memory a single request consumes so that, given a target concurrency, the required heap size and GC frequency can be estimated.

2. Test Steps

Create a new SpringBoot 2.5.4 project.

Add a POST endpoint ( create ) for JMeter to call and a GET endpoint ( gc ) that triggers System.gc() .

Configure a JMeter test plan with 10 threads, each performing 2,000 POST calls (total 20,000 calls).

Enable detailed GC logging in the JVM to record memory allocation in the young generation before and after each GC.

3. SpringBoot HTTP Endpoint Declaration

@Slf4j
@RestController
public class TestController {
    private AtomicLong count = new AtomicLong(0);

    @ResponseBody
    @RequestMapping(value = "create", method = RequestMethod.POST)
    public String create(@RequestBody Order order) {
        //log.warn("Received order cnt{}:{}", count.getAndIncrement(), order);
        return "ok";
    }

    @ResponseBody
    @RequestMapping(value = "gc", method = RequestMethod.GET)
    public String gc() {
        System.gc();
        return "ok";
    }
}

4. JMeter Test Plan

A thread group with 10 threads, each looping 2,000 times, is created. The HTTP Request defaults are set, the Content‑Type header is added for JSON payloads, and the request body contains a small JSON object (≈50 bytes).

5. JVM Configuration

The application runs with a 4 GB heap, 2 GB young generation, and the following GC options (including detailed GC logs):

java -server 
-Xmx4g -Xms4g -XX:SurvivorRatio=8 -Xmn2g 
-XX:MetaspaceSize=512m -XX:MaxMetaspaceSize=1g -XX:MaxDirectMemorySize=1g 
-XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCCause -XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution 
-XX:+UnlockDiagnosticVMOptions -XX:ParGCCardsPerStrideChunk=32768 
-XX:+PrintCommandLineFlags -XX:+UseConcMarkSweepGC -XX:+UseParNewGC 
-XX:ParallelCMSThreads=6 -XX:+CMSClassUnloadingEnabled 
-XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelInitialMarkEnabled 
-XX:+CMSParallelRemarkEnabled -XX:+CMSScavengeBeforeRemark -XX:+PrintHeapAtGC 
-XX:CMSFullGCsBeforeCompaction=1 -XX:CMSInitiatingOccupancyFraction=70 
-XX:+UseCMSInitiatingOccupancyOnly -XX:+PrintReferenceGC 
-XX:+ParallelRefProcEnabled -XX:ReservedCodeCacheSize=256M 
-Xloggc:/Users/testUser/log/gc.log 
-jar target/activiti-0.0.1-SNAPSHOT.jar

6. Experiment Process

Before the load test, a manual GC is performed to clear existing objects. Then the JMeter plan is executed, invoking the POST endpoint 20,000 times. After the run, GC logs are examined to calculate the total young‑generation memory growth, which corresponds to the memory allocated by the HTTP calls.

7. Results

Even with a tiny request body (≈50 bytes), each HTTP call allocated roughly 34 KB of heap memory. Adding a log statement increased the per‑request consumption to about 56 KB . When the detail field was expanded to 1,200 characters, the average rose to 36 KB , indicating that most of the allocation occurs inside SpringBoot rather than from request‑body copying.

In the author’s production environment, a single RPC request can consume between 0.5 MB and 1 MB due to complex business logic, multiple downstream calls, and extensive logging.

8. Conclusions & Recommendations

• Control the size and frequency of log statements, as they significantly affect memory usage and GC pressure. • Use the described measurement method to estimate required heap size for a given concurrency level. • Adjust JVM GC parameters based on observed GC frequency to avoid excessive pauses.

Javaperformance testingJMeterSpringBootGCMemory Profiling
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.