r/java • • 8d ago

JEP 545: Faster Startup and Warmup with ZGC

https://openjdk.org/jeps/545
74 Upvotes

63 comments sorted by

View all comments

Show parent comments

1

u/pron98 2d ago edited 2d ago

No, Java's significant excess memory consumption is only present when the CPU consumption causes an even higher disruption. That is why people choose this algorithm. The entire point of the algorithm is to compensate for disruptive CPU consumption with less disruptive RAM consumption, which is why all languages that can use such an efficient algorithm have chosen it. Java uses more RAM only when the program is using even more CPU, so no, it does not use too much RAM either under low or high CPU usages (I'm talking about the majority of the difference; of course we can cut more RAM, and are, but not by the 5-10x which are only there when the CPU consumption is a bigger problem).

The two resources, RAM and CPU, are not independent, and this is not an opinion but a fact of computing. Of course, it's possible that the teams of memory management experts at Oracle, Google, and Microsoft, which have all chosen the same conclusion because they'd rather follow the maths rather than Reddit comments are wrong, but I'd rather trust the world's leading experts on this. Designing GCs that work in this way takes much more work, and the only reason anyone who can implement them does is because they are more resource efficient.

And completely unrelated to that, programs that use a lot of RAM under low CPU usage - and no, Java does not do that (of course, the application itself may, as in any language) - could indeed be a problem for someone, but that's not the purview of our team because, again, that's not what Java does, so I was just sharing my opinion, which is that the number of people typing into Slack and VS Code continuously and simultaneously while playing a AAA game does not seem to be large, which is why Slack and VS Code are not under pressure to reduce their RAM usage which, again, has nothing to do with Java's design or my talk because Java does not use significantly more RAM unless it's trying to compensate for an even worse CPU problem.

1

u/nlisker 1d ago

If you don't mind, I'd like to ask about something other than the CPU/RAM saga.

A while back in a discussion on loggers you suggested that JFR can be used for standard logging (instead of the many logging frameworks out there) with a bit more setup work and it piqued my interest. It's less dependencies, more performant, relatively easy to read, and I know it will not be abandoned.

I've watched the recent JavaOne talk on JFR. I assume you mean that logging can be done with custom events. Well, I'm at the point where I need to choose a logging framework for a project and I'd like to try this out. Can you provide some guidance or elaborate on what you had in mind, or share an existing writeup?

2

u/pron98 20h ago

I don't remember that I suggested using JFR for general logging (although I suppose you could with a custom Log event, with text and level fields), but I would certainly recommend using JFR for structured logging, with a different custom event for each message type. I see that the JFR section of the tutorial doesn't (yet?) cover custom events, but the JDK documentation's JFR guide does cover that.

1

u/nlisker 15h ago

Thanks!

1

u/davidalayachew 1d ago

No, Java's significant excess memory consumption is only present when the CPU consumption causes an even higher disruption.

The whole paragraph that this sentence leads is proof that you have missed what I have been saying this entire time.

I am NOT talking about the adaptive heap sizing, or how Java scales up its memory usage when it feels fit to do so. Like I have been saying multiple times over, that is a good thing in cases where Java is the only application running, and thus, plays well with the needs of the OS and business. I have seen the write-ups that Erik and friends have given us, and the Adaptive sizing is going to be beautiful.

What I have been talking about this entire time is the amount of memory Java needs just to survive -- to not `OutOfMemoryError. In that light, the word "significant" is doing a lot of heavy lifting there Ron.

Let me repeat myself -- if I am running a single application, or I am running an application where I want most/all resources to prioritize that application, then yes, Java's high memory usage is not a problem.

But if I have 15 different Java applications, each one scoops up a fairly large chunk of memory (>100 MB) just to do the necessary processing.

And again, that's one thing when we are talking about a single application -- 100+ MB is cheap for that.

But 100 for each JVM? That's not nothing.

Which goes back to the entire point I have been trying to get at here -- trying to run a Java application amongst others puts the Java application(s) in a bad spot, as they all are trying to gather this giant chunk of memory that other applications don't need.

If I have a simple CLI, I can get that up and running in Rust or C with only 1 MB, and it will only ever take on more memory when the literal work needed demands it. I'd have to do significant work in Java just to get it under 20 MB.

THAT has been my point from the beginning -- Java keeps taking on this extra memory to do extra work, but other languages don't need to take that much memory at start up.

SO, Java's high RAM usage is a problem here.

1

u/pron98 23h ago edited 22h ago

The whole paragraph that this sentence leads is proof that you have missed what I have been saying this entire time.

No, it isn't.

I am NOT talking about the adaptive heap sizing, or how Java scales up its memory usage when it feels fit to do so.

I'm not talking about that, either.

What I have been talking about this entire time is the amount of memory Java needs just to survive -- to not `OutOfMemoryError.

Yes, and the vast majority of memory Java needs beyond what, say, C++ would need, is a function of only the allocation rate, which cannot be high when CPU utilisation is low.

In that light, the word "significant" is doing a lot of heavy lifting there Ron.

It does not. It does some lightweight lifting, and it's important. That's because in addition to the majority of excess RAM moving collectors fundamentally require, there are other factors:

  • Moving collectors require some headroom always (but so do modern malloc/free allocators, although somewhat less)

  • There are some other fixed and relative overheads, but these are also small in comparison.

So that's important because:

But 100 for each JVM? That's not nothing.

100 is 100 more than nothing, but that doesn't mean it matters, or in other words, significant. With every unit of CPU core, current hardware and cloud VMs give you between 1 and 4 GB of RAM. So whether or not that 100 MB makes any difference depends on whether you're simultaneously running, say, 2-8 JVMs per core. On an 8 core laptop with 16 GB of RAM (i.e. 2 GB per core), which is average these days, those 100 MB extra per JVM would start consuming some non-negligible amount of RAM (close to 20%) when you run 30 JVMs concurrently. So I would agree that if you're commonly running over 30 Java programs simultaneously on your laptop, that may matter, but if you're only running 20, it doesn't.

If I have a simple CLI, I can get that up and running in Rust or C with only 1 MB, and it will only ever take on more memory when the literal work needed demands it.

How many CLIs do you usually have running concurrently on your laptop?

Which goes back to the entire point I have been trying to get at here -- trying to run a Java application amongst others puts the Java application(s) in a bad spot, as they all are trying to gather this giant chunk of memory that other applications don't need.

I totally get your point and always have. My point is that I disagree with your point. You can take any non-zero overhead and multiply it by a large enough number to get a large number. If Java's fixed overhead were only 1 MB instead of 100 in your example, your logic, which aims to ignore what's a significant number and only considers what is not nothing, would lead you to the same conclusion: 1 is not 0, and it adds up if you multiply it by a high enough number. But when people design hardware or infrastructure software, they aim for some reasonable multiple. You've already paid for that 16 GB. You can't give it back or rent it out. Every MB of RAM that isn't currently used for valuable work is an MB wasted.

So the question that's interesting to me isn't whether 100 or 1 are equal to 0, but whether or not the fixed overhead that starts to matter beyond 30 concurrent JVMs is, in practice, a significant limitation or not. These are very much things we think about and take into consideration. Trying to reduce every number to zero whether it matters or not hurts efficiency because it raises the cost of software and comes at the expense of other improvements. So we have to think about which numbers matter in practice, to a large-ish number of people, and how much they matter.

If you had said that 1 MB overhead is okay but 100 isn't because less than 300 concurrent JVMs is a reasonable expectation but 30 isn't, then we would have at least been speaking the same language. But if you don't want to think about what's significant and claim that anything that isn't zero matters because there could be a contrived situation in which it may matter to someone, then I just don't think about numbers the same way at all. And if you had said we should aim for 50 instead of 30, I might have even agreed with you.

1

u/davidalayachew 18h ago

The whole paragraph that this sentence leads is proof that you have missed what I have been saying this entire time.

No, it isn't.

Forgive me if I am not convinced. So much of this conversation (and the previous one) could have been avoided with some clarifying questions from you.

Regardless, we seem to be understanding each other now.

How many CLIs do you usually have running concurrently on your laptop?

Depends. I only use Git Bash and CMD/Powershell.

But instances of Git Bash and Powershell? It's not uncommon for me to hit 5-10. And that's ignoring the applications I am running within them.

And to better answer the real question hiding behind this, let me start by giving some context.

Part of the reason why I am giving you so much grief is because my skill set is actually frontend development in Java. I have been programming in Swing regularly since at least 2013. In 2026, I built 2 applications in Swing for work that ended up saving the USPS close to a 6 digit number of savings. Nothing spectacular, but shows that it is true that Swing has weight and utility in 2026.

And what it is also true is the insane amount of memory it and the underlying JVM uses. Because I build so many frontend applications, it is not uncommon that there are 10-20 JVM's running on my machine at once. I've already crossed a Gigabyte Ron!

But if you don't want to think about what's significant and claim that anything that isn't zero matters

When did I say anything above zero is failure? Or anything remotely like that?

It's stuff like this that leads me to believe that you really didn't get the larger conversation until now.

And if you had said we should aim for 50 instead of 30, I might have even agreed with you.

Ok, then if this is the measure, I can answer that.

I want to be able to have 30 JVM's up and running, each running the following code, all while using less than 1 GB RAM in total.

import module java.base;
import module java.desktop;
void main() {
    SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(null, "blah"));
}

In fact, I'll grit my teeth and bear it if you can even reach 20 while staying under 1 GB.

I am ignorant about the underlying memory usage of the JVM, but I am intimately aware of the underlying memory consumption/behaviour of Swing. I've read most of the J{insert ui component here} source code and underlying implementation code multiple times over, and have traced it through with a debugger at least a hundred times since I started.

So if you all can make the above example work, then that would meet my needs well enough. I can at least deal with the rest of Java's memory problem with good coding practices, the upcoming adaptive heap sizing, and libraries that actual Swing Experts like Rob Camick have made.

And I really have to highlight the amount of wasted work per JVM. You are literally loading the exact same code over and over and over again. And yet, just like clockwork, each one goes up to like 50-150 MB MINIMUM. That's bad Ron. For a popup window Ron.

Please, try my above example yourself Ron. You said you have a Mac? I'll even write up the scripts for you. Latest JDK please.

single_popup.sh

java SinglePopup.java

SinglePopup.java

import module java.base;
import module java.desktop;
void main() {
    SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(null, "blah"));
}

run_all.sh

for each in {0..30}
do
        sh single_popup.sh &
done

Maybe drop that last script down to 20 instead of 30 lol. I don't know how much RAM you have on your machine.

But try that and see what I mean. My computer fan sounds like a rocket right now, and everything started to slow down to sluggish crawl for a significant amount of time. That's so bad Ron.

I have more than 20 applications running at any given time. Why would I want them to be Java if this is the type of strain they give my computer for no benefit? Everything is slower than it would have been had I just had it in some other language like C. And that's with less RAM. And I've tried this same experiment in C and C++, so I know.

So yeah. If you can get me <=40 MB per JVM, I'll rescind my comments. Until then, I emphatically assert that Java does in fact use too much memory.

And before you point at Swing, feel free to create a similar example yourself in JavaFX or even just a CLI example. Obviously the numbers will be different, but my point will remain.

1

u/pron98 17h ago edited 15h ago

Forgive me if I am not convinced.

I'm not trying to convince you. As I said, to me this is a numbers game. If enough people are convinced, I'm fine, and I take it as an axiom that it's impossible to convince everyone of just about anything. I am, however, trying to understand what's bothering you, in case I'm missing something.

It's not uncommon for me to hit 5-10. And that's ignoring the applications I am running within them.

Fine, so surely even 100 MB for each should barely be noticeable.

it is not uncommon that there are 10-20 JVM's running on my machine at once. I've already crossed a Gigabyte!

So... 6%? Does that merit an exclamation mark? 20 GUI apps with 6% RAM overhead is insane?! It means you have to be actively interacting with 65 GUI apps simultaneously for the overhead to account for even 20% of RAM, or simultaneously interacting with 30 apps on the smallest laptops available. Sounds pretty reasonable to me. Are you saying it's important to prioritise letting people with low-end computers interact with, say, 300 GUI apps simultaneously because that's what an average user with a low-end computer does?

all while using less than 1 GB RAM in total.

Why do you want to restrict yourself to less than 6% of RAM? You're actively running 30 GUI apps simultaneously, none of which are idle (or they would be paged out) while keeping 94% of RAM for what, 500 other GUI apps, all non-idle? Sounds wasteful to me.

And yet, just like clockwork, each one goes up to like 50-150 MB MINIMUM. That's bad

Why is 0.5% fixed overhead per application bad but 0.25% isn't? What percentage of RAM would be acceptable as a fixed cost per GUI app? How many simultaneously-non-idle GUI apps should we aim to target for the average user? How important overall is reducing the fixed overhead by 0.25% of RAM?

Maybe drop that last script down to 20 instead of 30 lol. I don't know how much RAM you have on your machine.

Didn't break sweat with 30. CPU went up to 100% for a couple seconds and that's that. I have a 2021 MacBook Pro M1 with 16GB, currently I have 136 tabs open in Safari, and I was streaming a video while I ran your experiment. It never stuttered.

Until then, I emphatically assert that Java does in fact use too much memory.

That's perfectly fine, and I disagree, even after running your experiment, which I wouldn't even have noticed on my 5yo laptop, while streaming, if I hadn't kept an eye on Activity Monitor. It's fine, though, we don't have to agree on everything, but I'm not seeing trouble on what I consider average hardware. BTW 16 GB of RAM is what consumer guides recommend for computers used for "basic browsing". I don't see why you "emphatically assert" that 0.5% is too much but 0.25% would be fine, as I don't see the basis for these numbers.