# Out of memory issue - heap memory

**URL:** <https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007>\
**Category:** Gatling (Open-Source)\
**Created:** [May 20, 2024, 4:09pm UTC](https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007 "2024-05-20T16:09:35Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![domin](https://avatars.discourse-cdn.com/v4/letter/d/977dab/32.png) [@domin](https://community.gatling.io/u/domin)\
**Post date:** [May 20, 2024, 4:09pm UTC](https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007/1 "2024-05-20T16:09:35Z")

</div>

**Gatling version** :3.9.0.4  
**Gatling flavor** : java  
**Gatling build tool** : gradle

When we have test that includes large payloads we are getting OOM heap memory issue (large payload is 1.06 MB). I have noticed after running profiling that objects stays in the memory and that cause OOM.

```auto
    public static final class StartedData implements ThrottlerActorData, Product, Serializable {
        private final Throttles throttles;
        private final ArrayBuffer<ThrottledRequest> buffer;
        private final long tickNanos;
        private int count;
        private final double requestStep;

```

This lead me to this code and I have noticed that all requests are stored in ArrayBuffer buffer - is there is a reason for that, is there is anything we can do about it.  
I also investigated GC and I can notice that Old Generation space is filling vary quickly and looks like GC has no chance to clear it.  
Please let me know if you need any more information. Thanks

---

<div class="post-metadata">

**Author:** ![slandelle](https://dub1.discourse-cdn.com/flex013/user_avatar/community.gatling.io/slandelle/32/4_2.png) [@slandelle](https://community.gatling.io/u/slandelle)\
**Post date:** [May 20, 2024, 8:15pm UTC](https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007/2 "2024-05-20T20:15:33Z")

</div>

Have you read `throttle`’s [documentation](https://docs.gatling.io/reference/script/core/simulation/#shaping-throughput)?

---

<div class="post-metadata">

**Author:** ![domin](https://avatars.discourse-cdn.com/v4/letter/d/977dab/32.png) [@domin](https://community.gatling.io/u/domin)\
**Post date:** [May 21, 2024, 9:03am UTC](https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007/3 "2024-05-21T09:03:02Z")

</div>

Thanks for the link. I read it and I think this one is most important part for us:

> - Beware that all excess traffic gets pushed into an unbounded queue, possibly resulting in an OutOfMemoryError if your normal throughput is way higher than the normal one.

We kind of try to mitigate that issue by introducing large payload probability where we can specify percentage of large payload. We managed to run successfully where LP is 1% but anything higher we see OOM. We need to prove that we can support 5% LP.  
So what I’m getting from docs you kindly provided only way to achieve that is lower throughput or time or both. Other options I suppose is just give it loads of memory - which we already do as ur setup is : `-Xmx12G -Xms1G -Xmn6G`  
We are using

```auto
 ScenarioBuilder sendJsonPayloads = new SendJsonPayload(username, password, url, testId).get(parameters.getRecordsPerRequest(), parameters.getLargePayloadProbability());
    ScenarioBuilder sendNdjsonPayloads = new SendNdjsonPayload(username, password, url, testId).get(parameters.getRecordsPerRequest(), parameters.getLargePayloadProbability());
    HttpProtocolBuilder httpProtocol = new Protocol().getBuilder(url).shareConnections();

    {
        setUp(
                sendJsonPayloads.injectOpen(constantUsersPerSec(baseRequestsPerSec).during(totalDuration)),
                sendNdjsonPayloads.injectOpen(constantUsersPerSec(baseRequestsPerSec).during(totalDuration))

        ).throttle(buildSteps()).protocols(httpProtocol);
    }

```

Is there is anything else we can do?

---

<div class="post-metadata">

**Author:** ![slandelle](https://dub1.discourse-cdn.com/flex013/user_avatar/community.gatling.io/slandelle/32/4_2.png) [@slandelle](https://community.gatling.io/u/slandelle)\
**Post date:** [May 21, 2024, 9:06am UTC](https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007/4 "2024-05-21T09:06:50Z")

</div>

Don’t use throttle. Properly shape your injection profile to generate the expected rps.

---

<div class="post-metadata">

**Author:** ![domin](https://avatars.discourse-cdn.com/v4/letter/d/977dab/32.png) [@domin](https://community.gatling.io/u/domin)\
**Post date:** [May 21, 2024, 9:12am UTC](https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007/5 "2024-05-21T09:12:54Z")

</div>

I do not fully understand why these objects are kept for so long. I would like to run scenario and once it is finished I do not keep holding of that object. Is this is case of using injectOpen and so many concurent requests and this is what filling the memory so quickly. I guess using closedInjection would resolve this issue but it would not be correct test in our case. Please let me know if my thinking is correct.  
This is example of our scenario

```auto
public class SendNdjsonPayload extends BaseScenario {

    public static final String SCENARIO_NAME_BASE = "send-ndjson-payloads";
    private final List<Integer> EXPECTED_HTTP_STATUSES = Arrays.asList(200, 204);

    public SendNdjsonPayload(String username, String password, String url, UUID testId) {
        super(username, password, url, testId);
    }

    public ScenarioBuilder get(int objectsPerRequest, double largePayloadProbability) throws JsonProcessingException {

        return scenario(SCENARIO_NAME_BASE)
                .group(SCENARIO_NAME_BASE + "-" + objectsPerRequest + "-objects-per-request").on(
                        exec(session -> {
                            try {
                                return session.set("payload", requests.generateNdjson(objectsPerRequest, largePayloadProbability));
                            } catch (JsonProcessingException e) {
                                throw new RuntimeException(e);
                            }
                        })
                                .exec(
                                        requests.postNdjsonPayload()
                                                .check(status().in(EXPECTED_HTTP_STATUSES)).transformResponse((response, session) -> {

                                                    if (EXPECTED_HTTP_STATUSES.contains(response.status().code())) {
                                                        LoadTest.addRecordCount(objectsPerRequest);
                                                    }
                                                    return response;
                                                })
                                )
                                .exec(session -> {
                                    // Explicitly remove the payload from the session after it's used
                                    return session.remove("payload");
                                })
                );
    }
}

```

---

<div class="post-metadata">

**Author:** ![slandelle](https://dub1.discourse-cdn.com/flex013/user_avatar/community.gatling.io/slandelle/32/4_2.png) [@slandelle](https://community.gatling.io/u/slandelle)\
**Post date:** [May 21, 2024, 9:19am UTC](https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007/6 "2024-05-21T09:19:25Z")

</div>

IMO, `throttle` is a super bad idea. It was introduced in Gatling because some users kept on requesting a port of the `Ultimate Thread Group` from the JMeter plugins project.  
As explained in the documentation, it pushes all the extra traffic into a queue. As a result, if you’re injection users faster than your throttle, you’re going to quickly fill the heap.

I’m more and more considering deprecating `throttle` for removal. The expected result can be achieved by properly designing the injection profile.

---

<div class="post-metadata">

**Author:** ![domin](https://avatars.discourse-cdn.com/v4/letter/d/977dab/32.png) [@domin](https://community.gatling.io/u/domin)\
**Post date:** [May 21, 2024, 9:22am UTC](https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007/7 "2024-05-21T09:22:46Z")

</div>

Thanks for help. I will try it out.

---

<div class="post-metadata">

**Author:** ![domin](https://avatars.discourse-cdn.com/v4/letter/d/977dab/32.png) [@domin](https://community.gatling.io/u/domin)\
**Post date:** [May 21, 2024, 12:13pm UTC](https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007/8 "2024-05-21T12:13:41Z")

</div>

Thanks I have changed the code so not using throttle now:

```auto
 {
        setUp(
                sendJsonPayloads.injectOpen(
                        rampUsersPerSec(1).to(baseRequestsPerSec).during(rampTime),
                        constantUsersPerSec(baseRequestsPerSec).during(baseHoldTime),
                        rampUsersPerSec(baseRequestsPerSec).to(spikeRequestsPerSec).during(rampTime),
                        constantUsersPerSec(spikeRequestsPerSec).during(spikeHoldTime),
                        rampUsersPerSec(spikeRequestsPerSec).to(baseRequestsPerSec).during(rampTime),
                        constantUsersPerSec(baseRequestsPerSec).during(baseHoldTime / 2)
                ),
                sendNdjsonPayloads.injectOpen(
                        rampUsersPerSec(1).to(baseRequestsPerSec).during(rampTime),
                        constantUsersPerSec(baseRequestsPerSec).during(baseHoldTime),
                        rampUsersPerSec(baseRequestsPerSec).to(spikeRequestsPerSec).during(rampTime),
                        constantUsersPerSec(spikeRequestsPerSec).during(spikeHoldTime),
                        rampUsersPerSec(spikeRequestsPerSec).to(baseRequestsPerSec).during(rampTime),
                        constantUsersPerSec(baseRequestsPerSec).during(baseHoldTime / 2)
                )

        ).protocols(httpProtocol);
    }

```

I still however get OOM but this time it is Request class - io.gatling.http.client.Request this is then used by HttpClient I believe. I can see this is holded again in the memory - any idea why? Thanks

---

<div class="post-metadata">

**Author:** ![slandelle](https://dub1.discourse-cdn.com/flex013/user_avatar/community.gatling.io/slandelle/32/4_2.png) [@slandelle](https://community.gatling.io/u/slandelle)\
**Post date:** [May 21, 2024, 12:16pm UTC](https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007/9 "2024-05-21T12:16:22Z")

</div>

I guess your machine is not powerful enough to process the IO you’re generating.

---

<div class="post-metadata">

**Author:** ![domin](https://avatars.discourse-cdn.com/v4/letter/d/977dab/32.png) [@domin](https://community.gatling.io/u/domin)\
**Post date:** [May 21, 2024, 12:19pm UTC](https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007/10 "2024-05-21T12:19:29Z")

</div>

Possible I will try on bigger one - cheers.

---

<div class="post-metadata">

**Author:** ![GatlingPete](https://dub1.discourse-cdn.com/flex013/user_avatar/community.gatling.io/gatlingpete/32/1167_2.png) [@GatlingPete](https://community.gatling.io/u/GatlingPete)\
**Post date:** [May 21, 2024, 12:45pm UTC](https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007/11 "2024-05-21T12:45:44Z")

</div>

Hi there,

Another option would be to give Gatling Enterprise a try. With the Enterprise version you can easily scale up and add additional machines working together to achieve the load you’re trying to create. You can give it a try for free at [cloud.gatling.io](https://Cloud.gatling.io) or contact us to set up a demo.

All the best,  
Pete

---

<div class="post-metadata">

**Author:** ![system](https://europe1.discourse-cdn.com/flex013/uploads/gatling2/original/2X/b/b148e0742de35c6280726cabf3ecd3de2d320f63.png) [@system](https://community.gatling.io/u/system)\
**Post date:** [June 20, 2024, 12:46pm UTC](https://community.gatling.io/t/out-of-memory-issue-heap-memory/9007/12 "2024-06-20T12:46:08Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
