[HN Gopher] Mark-Scavenge: Waiting for Trash to Take Itself Out
       ___________________________________________________________________
        
       Mark-Scavenge: Waiting for Trash to Take Itself Out
        
       Author : vips7L
       Score  : 67 points
       Date   : 2024-11-24 17:40 UTC (5 hours ago)
        
 (HTM) web link (inside.java)
 (TXT) w3m dump (inside.java)
        
       | A4ET8a8uTh0 wrote:
       | What a time to be alive, I read it the opening fully expecting to
       | see an open source automated trashcan that takes itself to the
       | curb each Monday. I was disappointed to find out it is about an
       | actual garbage collection algorithm.
        
         | garblegarble wrote:
         | I know this is completely off-topic, but you might be
         | interested in this[1] YouTuber who did something not far off
         | that...
         | 
         | 1: https://www.youtube.com/watch?v=VhYEOG9LOIk
        
       | kibwen wrote:
       | _> Modern garbage collection assumes that the weak generational
       | hypothesis holds and that most objects die young_
       | 
       | Aside, I'm curious how first-class support for value types and
       | Go-style stack allocation via escape analysis changes the value
       | proposition of the generational hypothesis. If we hypothesize
       | that short-lived objects are local to a single function scope
       | (and thus eligible for stack allocation either explicitly via a
       | value type or heuristically via escape analysis) then it might
       | completely upend the generational hypothesis and make it so that
       | relatively more long-lived objects are getting heap-allocated.
       | Surely someone's done some studies on this?
        
         | DamonHD wrote:
         | AFAIK not nearly enough stuff gets caught by escape analysis -
         | and thus stack allocated - to make a difference.
        
           | kibwen wrote:
           | I'm open to believing that this is true, but some real
           | numbers would be nice. Surely it wouldn't be a hugely
           | invasive change to fork the Go compiler, change the stack
           | allocation check to `return false`, and then measure the
           | overhead of the garbage collector on real Go programs with
           | stack allocation both enabled and disabled.
        
             | DamonHD wrote:
             | I may have been answering past you - I am thinking of Java
             | running on the JDK here. And indeed I may be out of date
             | also.
        
               | cempaka wrote:
               | Yeah in Java land specifically I think the question would
               | become, "does the generational hypothesis still hold up
               | once we have Valhalla and a much larger share of short-
               | lived objects are stack allocated as value types?" but of
               | course it may be years until the ecosystem reaches that
               | point, if ever.
        
               | neonsunset wrote:
               | As shown by C#, it will generally continue to be relevant
               | since both primarily use JIT compilation with ability to
               | modify code at runtime which can violate inter-procedural
               | escape analysis assumptions leading to heap allocations
               | of the objects that are passed down to the callees (there
               | is work scheduled for .NET 10 to address this, at least
               | for AOT compilation where interproc analysis conclusions
               | will be impossible to violate).
               | 
               | You can craft a workload which violates the hypothesis by
               | only allocating objects that live for a long time but
               | both JVM and .NET GC implementations are still much
               | faster designs than Go's GC which prioritizes small
               | memory footprint and consistent latency on _low_
               | allocation traffic (though as of .NET 9, SRV GC puts much
               | more priority on this, making similar tradeoffs).
        
               | cempaka wrote:
               | > _ability to modify code at runtime_
               | 
               | Would Java's moves towards "integrity by default" mean
               | that this could be ruled out in more cases?
        
               | DamonHD wrote:
               | Ahem --- JDK => JVM!
        
             | DarkNova6 wrote:
             | The reason escape analysis is not "good enough" is why we
             | have project Valhalla trying to bring Value Types into the
             | JVM.
             | 
             | I don't have numbers at hand, but I remember the JDK Expert
             | Group talking about this extensively in the past and why
             | they deferred bringing Value Types for such a long time.
             | They hoped complex enough EA can get rid of indirections
             | and heap allocations but it just wasn't powerful enough,
             | even with all advances throughout the years.
        
           | fweimer wrote:
           | Historically, Hotspot's escape analysis only resulted in
           | avoided heap allocations (via scalar replacement) if all uses
           | were inlined. I don't think this has changed.
        
           | eikenberry wrote:
           | Is there a language that makes this explicit, allocates the
           | variables on the stack via compiler enforced notation?
        
             | fanf2 wrote:
             | C, C++, Rust, Zig, ...
        
             | neonsunset wrote:
             | C# (.NET in general) :)
             | 
             | Well, variables cannot be forced to stack specifically.
             | They are placed in the "local scope". And that would
             | usually be either stack or CPU registers - thinking in
             | stack only is a somewhat flawed mental model.
             | 
             | Both C# and F# complicate this by supporting closures,
             | iterator and async methods which capture variables placing
             | them in a state machine box / display class instead which
             | would be located on the heap, unless stack-allocated by
             | escape analysis (unlikely because these usually cross
             | method boundaries).
             | 
             | However, .NET has `ref structs` (or, in F#, [<Struct;
             | IsByRefLike>] types) which are subject to lifetime analysis
             | and can never be placed on the heap directly or otherwise.
        
           | masklinn wrote:
           | Go has much more significant stack allocation capabilities,
           | most notably it has no problem allocating entire structs on
           | the stack so doesn't need scalar replacement, which falls
           | over if you breathe on it
           | (https://pkolaczk.github.io/overhead-of-optional/).
           | 
           | According to https://github.com/golang/go/discussions/70257#d
           | iscussioncom...
           | 
           | > the weak generational hypothesis does not hold up well with
           | respect to heap-allocated memory in many real-world Go
           | programs (think 60-70% young object mortality vs. the 95%
           | typically expected)
        
         | DarkNova6 wrote:
         | But stack allocated objects are not part of the heap and
         | therefore not even part of Garbage Collection? And afaik stack
         | allocation is already done for objects which don't escape a
         | method.
        
         | masklinn wrote:
         | > it might completely upend the generational hypothesis
         | 
         | The generational hypothesis is about object lifetime, and that
         | doesn't change.
         | 
         | It does change the relevance of the generational hypothesis to
         | garbage collection.
         | 
         | > Surely someone's done some studies on this?
         | 
         | The go team has, and that's why go doesn't have a generational
         | GC. The complexity of adding generational support, especially
         | in a mutation-based language (so needing memory barriers and
         | the like) was found not to benefit when a significant fraction
         | of the newborn objects don't even reach the youngen. See
         | https://github.com/golang/go/discussions/70257#discussioncom...
         | from the current discussion of adding opt-in ad-hoc support for
         | memory regions.
        
         | uluyol wrote:
         | You might be interested in this talk:
         | https://go.dev/blog/ismmkeynote
        
         | ithkuil wrote:
         | If you flip the argument on its head you can frame it as: since
         | most objects die young it's very likely they will stay on the
         | stack and thus it makes sense to invest in an allocation-site
         | optimizer that will put the object on the heap only if static
         | escape analysis says it may escape the lexical scope.
        
       | fweimer wrote:
       | How does this relate to Shenandoah's region selection logic?
       | Doesn't it have similar behavior?
        
       ___________________________________________________________________
       (page generated 2024-11-24 23:00 UTC)