Earlier quoted context omitted.
We compiled one of our Java app to native binary using GraalVM (for encyption and secret managment needs). Side effect is the Java native binary performance is excellent, app startup time also significantly less compared to JVM version. I am not sure how it compares with C++, Rust and Zig, but we made a benchmark with a similar Go binary, Java native version performance (load tests) is similar to Go binary. Only RAM…
The RAM difference is primarily because both Native Image (what you call Graal VM) and Go use much simpler and less efficient memory management techniques. HotSpot uses much more RAM by design as there are inefficiencies caused by using too little of it. Memory management - and especially very sophisticated approaches that are only used by the best resourced teams - is an especially misunderstood aspect. I gave a tal…
Ah yes, the swapping induced by IntelliJ overflowing my system RAM is supposed to reduce the inefficiencies of using too little memory. Great...
Thanks pron, you've fully bought into all the JVM kool-aid talking points without ever trying to question them. One of the reasons I upgraded to 32 GB RAM in 2019 was to run a Minecraft modpack. Minecraft is one of the most memory intensive games I've ever played.
When you consider that the smallest cloud instances that cost $4 per month only give you like 512 MB of RAM and have refused to upgrade for at least a decade, the idea of using more than 512 MB to be "more efficient" is ridiculous. It raises your minimum costs to $10 per month.
>I gave a talk on the subject that I hope will be published soon, and while I can't reproduce it here, let me give an example that offers some basic intuition.
>Imagine needing to do some computation in two ways on a machine with 1GB of free RAM. You could run for 10s, taking up 100% CPU and consuming 80MB of RAM, or for 9s, taking up 100% CPU and consuming 800MB of RAM.
This is the "wasted RAM is unused RAM" mentality and it doesn't work, because you usually have multiple competing programs and when you run out of RAM, your system will start swapping. This will then require you to buy more RAM, leading to more leftover RAM, which is then wasted and gets consumed by the applications again. It's nonsense.
Then there is the fact that the vast majority, basically 99.9% of algorithms are not scalable in the naive way presented. Nobody will waste resources on writing the same algorithm twice for these two cases. Databases are usually designed to either be primarily file system backed or in-memory backed. They will use the extra memory to hold indices and let the OS do the caching or they will reserve all the memory up front, intentionally leaving nothing for other applications.
>The second is more efficient, despite taking up 10x more RAM and saving "only" 10% of CPU, regardless of the relative cost of RAM and CPU. This is because taking up 100% of the CPU effectively captures 100% of RAM (as no other program can use it), so both programs capture the entire 1GB only the second one captures it for a second less.
Ok, now you're just writing nonsense. Nowadays people have CPUs with multiple cores and use an OS with a scheduler. If you have two programs taking up 100% of the CPU, the OS will give each process some of the hardware resources. You can't just assume some 100% CPU blockage here just because it is convenient for your argument. It's especially dishonest since even a 99% CPU blockage basically makes your argument fall apart completely.
If you have two programs decide to 10x the memory consumption to save one second, you'll most likely run into swapping issues, which will actually lock up your system for several seconds at a time and if you're unlucky, the OOM killer strikes or the compositor freezes up and you have to reboot. You're saying that a 1 second savings is worth an endless amount of inconveniences.
>This scales to non extreme situations because accessing RAM requires CPU, so using CPU means capturing RAM whether you use it or not. So HotSpot uses it if it can use it to balance the CPU utilisation.
Again, this is completely incorrect in so many ways that you're bragging you know nothing about how modern computers work.
CPU cores have their own local memory resources called caches. Depending on how your code is written, you may tile your data so it fits entirely in cache and operate within the local memory.
When performing inter thread communication, there are often situations where the data often doesn't even get written and then loaded to main memory, since atomic operations can make use of the MESI cache coherency protocol to pull the data directly from another cores' cache.
Nowadays DMA is the standard way to perform large data transfers to hardware peripherals. If you load a file from an HDD, the SATA peripheral will communicate via DMA to copy whole sectors or file system blocks. The same applies to sending data to an SSD, network interface, GPU or basically anything else that performs bulk transfers (1 KiB+). The DMA engine is a separate component independent of the CPU and it may write data directly into cache as well.
Then there is the fact that RAM is a form of storage and storage is usually characterized by the fact that it takes up an area and said areas can be subdivided. When RAM is used, the portion of used RAM is considered blocked for the duration of how long it is stored, independently of whether it is accessed or not. This means that the most important objective is having sufficient amounts of RAM to store all data, not to occupy all of it preemptively even when it is not really needed.
The same can't be said of CPUs. Occupying the CPU usually means actively using the CPU. The only exception to this is things like spinlocks which should be avoided like the plague. By what the CPU is occupied is determined by the OS, therefore your logic is backwards. It's not the program blocking the CPU and therefore blocking the memory. The OS decided to stop running your process to run another process. Progress is slowed down, but it is not blocked.
Actual blockage only occurs when two processes compete for a fixed resource so that it is not possible to run both processes simultaneously, so that one process has to be closed to run another process.