Skip to content

Mark all objects reachable from roots as live before doing main cyclic GC pass #126491

Description

@markshannon

Objects can only be cyclic garbage if they are not reachable.
So, if we can cheaply identify the majority of reachable objects before performing the (relatively slow) cycle detecting pass, we can save a lot of time.

Performing a transitive closure of all objects reachable from global roots (the sys and builtins modules as well as builtin class's dicts and sublasses) plus a transitive closure of all objects reachable from the stacks can eliminate >90% of all objects relatively cheaply.

Initial experiments show a ~3% speedup, with an almost 50% speedup of the most gc-heavy benchmark.

This idea has been proposed a few times.
@nascheme has definitely suggested it before. Perhaps he can add links to any prior discussion and/or experiments?

What makes this more feasible now is that the GC can see the evaluation stack of frames, thanks to #124392, so we would now expect that the vast majority of reachable objects can be cheaply marked, thus improving the efficiency of cycle detection considerably.

Linked PRs

Activity

  1. added
    performancePerformance or resource usage
    interpreter-core(Objects, Python, Grammar, and Parser dirs)
    3.14bugs and security fixes
    on Nov 6, 2024
  2. kumaraditya303 commented on Nov 6, 2024

    @kumaraditya303
    Contributor

    Is that benchmark public, link isn't working for me?

  3. markshannon commented on Nov 6, 2024

    @markshannon
    MemberAuthor

    Fixed the link

  4. nascheme commented on Nov 6, 2024

    @nascheme
    Member

    FYI, I made an incremental "mark alive" version of my idea. My PR is based off of 3.13 but it could be done on top of the "incremental gc" that's in the "main" branch as well. This approach avoids a problem with the current incremental GC: if you happen to pull in an object near the root of the object graph, the GC pause could be long because all reachable objects are pull in to the cyclic GC pass.

    #126511

  5. added a commit that references this issue on Nov 18, 2024
  6. added 2 commits that reference this issue on Nov 18, 2024
  7. added a commit that references this issue on Dec 2, 2024
  8. eendebakpt commented on Dec 3, 2024

    @eendebakpt
    Contributor

    @markshannon Out of curiosity:

    • Which kind of objects are not reachable by the transitive closure of the global roots + stack, but are reachable in some other way so they are not collected by the GC?
    • Are there any statistics on the ratio of number of objects (or number of cycles) that iskept by the GC to the number that is deallocated by the GC?
  9. added
    type-featureA feature request or enhancement
    and removed
    3.14bugs and security fixes
    on Dec 3, 2024
  10. added a commit that references this issue on Dec 3, 2024
  11. nascheme commented on Dec 3, 2024

    @nascheme
    Member

    Python doesn't have a precise set of roots. For example, an extension module can create objects but not have them connected to any roots that the CPython runtime knows about.

  12. added 2 commits that reference this issue on Dec 4, 2024
  13. added a commit that references this issue on Dec 6, 2024
  14. added 2 commits that reference this issue on Dec 9, 2024
  15. encukou commented on Dec 10, 2024

    @encukou
    Member

    I've reverted the last change, which introduced a refleak.

  16. added 3 commits that reference this issue on Jan 8, 2025
  17. added 3 commits that reference this issue on Jan 12, 2025
  18. nascheme commented on Feb 26, 2025

    @nascheme
    Member

    Could this be closed now? Or, are we waiting for a revised version of gh-127519 to be merged? @markshannon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)performancePerformance or resource usagetype-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions