Skip to content

Release excess weak-map bucket capacity after GC removes the keys #204

Closed

Description

@dimensionscape

Hash::updateAfterGc in src/hx/Hash.h removes entries with dead weak keys and decrements size, but it does not reduce or release the bucket array. Ordinary remove() has a compaction path; GC-driven removal does not.

I reproduced this against checkout 03a4e8d on Linux x86_64 through WSL, Haxe 4.3.3 and HXCPP_M64. The native probe rooted a weak hash, filled it with 100000 object keys and integer values on an attached worker thread, then fully unregistered and joined that thread before collection. No keys were retained strongly afterward.

Before collection:

entries 100000, buckets 262144

After three major collections:

entries 0, buckets 262144, bucket bytes 2097152

The weak keys were correctly removed. This is retained capacity, not a failure to collect those keys. A long-lived cache can nevertheless keep a large empty table after a temporary burst. Hash marking, weak-value processing and cleanup also loop over bucketCount, so future collections still scan the empty buckets.

At minimum, consider releasing the bucket reference and resetting the count/mask when GC cleanup leaves size zero. For partially emptied maps, investigate a conservative shrink policy with hysteresis. Do not invoke the current compact()/InternalRealloc path blindly during GC cleanup, since it allocates managed memory while collection is in progress. Deferred shrinking on a later mutator operation may be appropriate.

Measure retained heap and subsequent collection time after bursts, then refill the map to check that capacity release does not cause excessive rehashing in oscillating caches. Cover Object WeakMap and the runtime's weak string sets where applicable, plus moving and generational modes. Related: #151 for benchmarks and #203 for the separate dependency-chain scanning cost.

Activity

  1. added a commit that references this issue on Oct 20, 2026
    77d9a6c
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