Skip to content

Measure linear grouping for GC free-list rebuilds instead of comparison sorting #206

Closed

Description

@dimensionscape

GlobalAllocator::createFreeList in src/hx/gc/Immix.cpp scans the blocks, builds mFreeBlocks, sorts the pointer array with std::sort and SmallestFreeFirst, then walks it again to build the size-class starting indices. Collect calls this before mutators resume.

SmallestFreeFirst compares only mMaxHoleSize. The current hole-size assignments derive from line counts shifted by IMMIX_LINE_BITS, so the key space is bounded by the block geometry and much smaller than the number of free blocks in a large fragmented heap. This suggests linear grouping/counting by hole size instead of comparison sorting.

This is a source-level performance candidate at checkout 03a4e8d. I have not measured the free-list phase's share of collection pauses or an alternative implementation. Establish that share before changing the algorithm.

Profile rebuild time separately on small heaps, large mostly-empty heaps and fragmented heaps with long-lived objects, under both default and big blocks. Record free-block count, hole-size distribution, allocation search cost, total pause distribution, retained heap and subsequent allocation throughput.

If this phase is material, compare bounded grouping that retains the current smallest-suitable-hole policy. Verify the key alignment/range for every supported configuration rather than assuming the default geometry. Reuse or bound any native scratch storage so the optimization does not replace sorting with an allocation spike during every collection.

The rebuilt order and mNextFreeBlockOfSize must remain consistent. Check GetFreeBlock ownership, pooled allocator reset and background zeroing, and preserve the policy of filling smaller available ranges first. Equal-sized blocks may also have locality effects worth measuring even though the current sort is not stable.

Require the normal, moving, generational, big-block and verifier stress coverage. Related: #151 for phase-aware performance tracking. This targets free-list rebuild work inside the pause, separate from #191's large-buffer lock scope and #201's remembered-set copying.

Activity

  1. dimensionscape commented on Oct 23, 2026

    @dimensionscape
    MemberAuthor

    Measured, and not worth changing. Rebuilding the free list, scan and sort together, takes this share of collection time on Windows:

    Workload Collections Free list Share Worst single rebuild
    Fragmented heap: 2 million small objects, every third kept, then garbage 200 1.9 ms of 728 ms 0.26% 0.02 ms
    GC stress test, 30 s, 8 threads, default blocks 2,050 352 ms of 16,274 ms 2.2% 0.34 ms
    GC stress test, 30 s, 8 threads, big blocks 2,100 194 ms of 16,486 ms 1.2% 0.25 ms

    The sort is only part of that, so replacing it with linear grouping could save a fraction of a percent of collection time at most.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions