5 ms·
This might be a stupid question but can't we mix the best of both worlds in a programming language? To have GC where it makes sense and doesn't add too much ove
by lbriner 5y ago
This might be a stupid question but can't we mix the best of both worlds in a programming language? To have GC where it makes sense and doesn't add too much overhead but allowing non-GC objects that require a bit more care and where you know you need to free memory yourself or using some basic smart_ptr-style tracking object?
Just like .net allows you to use "unsafe". It is a clear marker that you are stepping outside of the safe zone and need to be careful, but at least you can.
- flohofwoe 5y agoYou can already do that in any GC language (to some extent) by drastically reducing the amount and creation/destruction-frequency of garbage collected objects (for instance by reducing "object granularity" and using object pools). But this means that the programmer suddenly needs to actively think about memory management (and already in the design/planning phase, because later is too late), while the whole selling point of automatic memory management solutions was that this wouldn't be necessary anymore (which was a deception all along, but that's a different topic).
- rwmj 5y agoBut it's still a better trade off: The programmer can not think about memory management most of the time, but if they want to they can optimize hot paths in the code. Optimization (in all programming languages) often involves complicated and non-intuitive code backed by careful measurement.
- pradn 5y agoYes, this approach works best with the "premature optimization is the root of all evil" axiom. When I worked on high-performance servers in C#, we would occasionally find ways to 1) reduce allocations 2) make allocations either very short-lived so they stay in the short-term GC timeframe or very long-lived (object pooling/reuse or creating object-aggregates for pseudo-slab allocation).
- guenthert 5y ago> You can already do that in any GC language (to some extent) by drastically reducing the amount and creation/destruction-frequency of garbage collected objects (for instance by reducing "object granularity" and using object pools). Or allocating on the stack (just mind the size of the allocation and the current depth of the stack). Common Lisp offers the DYNAMIC-EXTENT declaration for that: http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/dec_dynamic-extent.html http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec...
- janto 5y agoTo some degree you could use a GC only language to create a large pool (eg a numpy array) and "allocate" items in there with indices as pointers. Would cover some of the use cases for manual memory management. edit: scooped by a sibling comment! :) ah well, here's what you could use to structure objects in a numpy array https://numpy.org/doc/stable/user/basics.rec.html?highlight=structured%20arrays https://numpy.org/doc/stable/user/basics.rec.html?highlight=...
- secondaryacct 5y agoThat s what we do in low latency java in big banks, 3 GC per day, between 5 and 6 am, anything more and 10 people are profiling.
- kaba0 5y agoIs that truly a good idea in case of the JVM? Of course there will be problems where this is the correct approach, but in certain cases simply letting the very advanced GC do its job is actually faster.
- bobbylarrybobby 5y agoIt’s not about speed (throughout) but about latency. If the GC takes (say) several minutes during a period of downtime so that it doesn’t have to run at all during uptime, then it’s worth it.
- kaba0 5y agoWhat about ZGC then? If throughput is not the metric to optimize for, ZGC promises less than 1 ms pauses for up to TBs of heap size.
- pjmlp 5y agoJava suffers from Python 2 like syndrome with Java 8. Those shops aren't going to use ZGC. Nor they will profit from the several performance improvements, including the free JIT cache across runs with PGO data on Hotspot and J9, that used to be a commercial feature on third party JDKs.
- rwmj 5y agoA strategy that works for some GC'd languages is to force a minor collection at some safe point and then run your "non-GC'd" code taking care to limit allocations to what fits in the minor heap. I wrote a small game using this strategy where the safe point happened before waiting for a vertical sync to refresh the screen (where otherwise we'd have been sitting around doing nothing).
- reecko 5y ago> To have GC where it makes sense and doesn't add too much overhead but allowing non-GC objects that require a bit more care and where you know you need to free memory yourself or using some basic smart_ptr-style tracking object? D is designed exactly like that. In fact, using value types and smart pointers (using `typecons`) is kind of required if you want to keep GC pauses tolerable. On the flipside, a simple GC means no additional overheads like write barriers or remembered sets. Additionally, a borrow checker for D has also been in development (I have not personally checked it out to comment on it though).
- Someone 5y agoSome languages have separate “value types” and “reference types” (https://en.wikipedia.org/wiki/Value_type_and_reference_type https://en.wikipedia.org/wiki/Value_type_and_reference_type) exactly for that reason, with value types being copied when passed into or returned from a function, so they never get shared. That makes it easy to determine whether they can be stack allocated. Intended use is to use value types for small immutable values (small because copying large objects is more costly, and immutable so that the copying doesn’t make a difference, semantically) That can significantly decrease the number of garbage collected objects and with it memory usage (the smaller the object, the larger the relative overhead of a few bytes of data for use by the garbage collector)
- throw149102 5y agoI think what you esssentially want is a language with a powerful effect system and substructural typing, along with regions for memory management. This is like what Rust does with ownership semantics and the borrow checker, where normal types are linear/affine, that is, they can only be used (exactly,at most) once. What would be more powerful is having some effect of GC'd function, and some effect of non-GC'd function, and you can only pass the barrier from GC to non-GC if it's a linear/affine type. But when you're in a GC function you can use whatever types you want to. So instead of being stuck with the borrow checker, you can just decide at a drop of a hat to enter GC mode to write your linked list.
- pjmlp 5y agoYes you can and plenty of them do. Have a look at D, Active Oberon, Modula-3, C#, F#, VB (6 and .NET), many BASIC dialects, Eiffel, Haskell (now with experimental lifetimes), Swift (RC is a GC algorithm), C++/CLI, C++/CX, Unreal C++, Common Lisp, among many others. The big problem is a big lack of quality when teaching CS subjects, so many learn GC and think all GC languages are like JavaScript.