Java app using abnormal amount of ram
lelebees
HOBBYOP

2 years ago

Attached you see the RAM usage graph of my project. I am running a discord bot with a Java Spring Boot application, and on my local device, the app eventually uses <200 mb of RAM, but on railway, the ram usage continues to increase. I found a StackOverflow post that tackles a similar issue, but updating my Dockerfile with the runtime flags did not deliver noticeable changes (see the last deployed commit, compared to the rest). Ideally, I don't have to manually call the GC, although it is an option available to me.

Does anyone have any recommendations for getting my Java app to release unused RAM memory?

23 Replies

lelebees
HOBBYOP

2 years ago

1a73e8f4-a61d-4a67-9bd7-3539b677698b


brody
EMPLOYEE

2 years ago

that's more so looking like a memory leak to me


lelebees
HOBBYOP

2 years ago

If it was, then i'd be able to reproduce that locally, no?


brody
EMPLOYEE

2 years ago

do you build from the dockerfile file and run the resulting image ?


lelebees
HOBBYOP

2 years ago

Yes


brody
EMPLOYEE

2 years ago

well it's not like railway is making up metrics


lelebees
HOBBYOP

2 years ago

According to stack it's because java isnt by default configured for containers, which is why i asked here if people had knowhow of how i should configure the dockerfile


lelebees
HOBBYOP

2 years ago

My apologies if I gave you the wrong answer to this question. I mean that Railway is running from the Dockerfile, and my local machine is the bare Java app. Local machine has less ram usage then the deployment on railway.

The attached stackoverflow post claims that java won't unclaim heap space the same way if it's running in a container. There were runtime flags i could add to the dockerfile that'd supposedly fix this, but this did not have the desired effect


brody
EMPLOYEE

2 years ago

what effect did it have, if any


lelebees
HOBBYOP

2 years ago

Practically none if it didnt make it worse


dayblox
HOBBY

2 years ago

Are you sure the flags were taken into account when deploying?


lelebees
HOBBYOP

2 years ago

How can I verify that?


dayblox
HOBBY

2 years ago

Logs


lelebees
HOBBYOP

2 years ago

A quick search doesn't give me any hits for the flags, so i guess they're not being considered


lelebees
HOBBYOP

2 years ago

I'll play with those when i get back home and see if i can get it working. Probably misusing them


lelebees
HOBBYOP

2 years ago

I am the most smoothbrained ape on this planet


lelebees
HOBBYOP

2 years ago

Flags go before the -jar flag 🤦


dayblox
HOBBY

2 years ago

Did it help your heap usage?


lelebees
HOBBYOP

2 years ago

Going to redeploy now and see if it helps


lelebees
HOBBYOP

2 years ago

I've had her run for a bit and it definitely looks like it helped. RAM usage continues to grow but does so much slower


lelebees
HOBBYOP

2 years ago

I'm trying if ShenandoahGC helps more. It looks promising so far


lelebees
HOBBYOP

2 years ago

It looks like shenandoahGC has given my app a healthier ram graph. Thank you all for your help!


lelebees
HOBBYOP

5 months ago

Apologies for necroposting my own thread, but after ~2 years I've found the root cause of the issue.

The good news? There's no memory leak!
The bad news? netty was responsible for ~50% of my heap usage (because of - get this - it's own network buffer reserving space it did not use), and ShenandoahGC wasn't quite built to suit my needs, which caused the (claimed) heap memory to grow ever so slowly. (I swapped to G1GC which does a great job of keeping the heap as big as it needs to be. In defense of ShenandoahGC: it was still leagues better then whatever the default GC was doing)

What's also growing slowly is my Metaspace size, the root cause of which is most certainly also my dependencies (there's about 18 - 19.000 classes loaded, of which i probably haven't even written 100.).

Let this be a lesson and a warning for other devs like me. Spring is convenient, but also quite taxing on resources. You should have a proper think about if you need it before committing to the framework, and then also what parts of the framework you need. In my case I have a dependency on spring-web which spins up a Tomcat server that I simply do not use (among other things), all just so I can have some mediocre syntax sugar for making HTTP requests for a single class.

Java has a pretty decent (albeit slightly cumbersome) HTTP API built-in, which was more then enough to suit my needs.


Loading...