3 ms·
Also, because GC is “lazy,” your program may even end up running faster than one that uses an “eager” memory management, such as the one used in C++, where dest
by Koshkin 5y ago
Also, because GC is “lazy,” your program may even end up running faster than one that uses an “eager” memory management, such as the one used in C++, where destructors are invoked, and objects on the heap are deallocated, early on, i.e. as soon as something goes out of scope, rather than when the process is close to running out of its memory quota (which may never happen).
- ceronman 5y agoYeah totally! And this not only applies for deallocation, but also for allocation. A generational GC with bump allocation for the young generation can be much faster than a naive C/C++ application using malloc for every single allocation. Of course you could use an arena in C/C++ to improve this, but it requires thinking ahead and it add some extra challenges to the design. A GC gives you this for free, you don't have to even think about it.
- kbenson 5y agoFaster isn't always the primary concern, sometimes memory matters a lot, and keeping memory usage down important (for example embedded, or even if the system just isn't dedicated to this one application so so the "memory quota" is not clearly defined at all times). That a GC might let you control this to a degree and choose the right approach for the current job is good though.
- pkolaczk 5y agoThat is a theoretical effect I frequently see mentioned, but never seen materialize in practice. Quite likely it is hidden by other things that affect Java performance negatively. Cache effects might play a role here as well. Deallocating memory immediately after use allows you to allocate it again when it is still hot in the cache. So eg if you're iterating a structure and doing lot of interleaved allocations/deallocations they are likely to not cause cache misses (assuming the allocator is not dumb and uses some kind of LRU strategy). With GC and deferred deallocation, you're moving a lot more data between the main memory and the caches, because memory for sure gets pushed out of cache by the time it is reclaimed. And additionally, GC has to touch quite a big number of objects when tracing (and move unneeded stuff to cache, and push needed stuff out of cache). Memory bandwidth is a scarce resource these days. If you want to see these effects in extreme, try running a GC based program in an environment that is low on memory but has swap enabled. Hitting the first full GC is basically performance game-over, regardless concurrent or not. On the other hand, manually managed apps can often deal with big chunks of their heap swapped out without terrible consequences.