Skip to content

perf(array): empty child arrays reserve 16 slots; 1.25 MiB of 1.50 MiB live array storage is unused in cyclic workload #11744

Description

@proggeramlug

Problem

Empty child arrays reserve 16 element slots even though roughly 75% of document nodes are leaves and keep an empty array; the remaining nodes hold four children. This is repeated tens of millions of times in the cyclic workload.

Measured 2026-10-01 on macOS arm64, Perry main d40ed1a47019bcae547819ebb5756bcd96ba1057 (v0.5.1655), with matching compiler and runtime archives. This snapshot already includes #11645. These are diagnostic probes; no compiler/runtime fix was applied and the original comparison remains unchanged.

crates/perry-runtime/src/array/header_gc_slots.rs defines MIN_ARRAY_CAPACITY = 16; general allocation paths in array/alloc.rs apply capacity.max(MIN_ARRAY_CAPACITY). This is distinct from #11659's allocation-size ceiling/hole-tail/read-guard work and from historical allocation-speed issue #63.

Measured capacity waste

A separate diagnostic source adds six explicit full-GC census points, classifying tracked allocations at mark completion before sweep. With the revision cache populated:

  • Approximately 5.16 MiB of reachable tracked heap data, including 10,920 DocNodes.
  • Arrays account for approximately 1.50 MiB.
  • 174,740 capacity slots versus 10,924 used slots; approximately 1.25 MiB of live-array storage is unused element capacity.

The diagnostic census changes GC scheduling and adds observer buffers; its RSS is not substituted for baseline RSS. No changed array allocator was benchmarked, so the capacity saving is an opportunity, not a measured CPU/RSS improvement.

Direction and acceptance

Explore zero/small initial element backing for empty/small arrays with normal growth. Preserve distinct mutable identities (do not share a mutable empty array), hole semantics, subclass/named-property handling, growth forwarding, and GC roots/barriers.

Re-run the cyclic workload linked below with unchanged source and checked output/parent/closure identities. Report live array bytes, capacity versus used slots, CPU and peak RSS; also measure growing-array workloads to detect reallocation regressions. Validate growth past initial capacity and retained parent-to-young-child edges under moving-GC stress.

Complete unchanged workload and method: #11743.

Evidence in the project-comparison workspace: demo/results/stress/perry-profile/summary.md, profile-manifest.json, cpu-summary.json, experiment-summary.json, experiments.json, gc-diagnostics.stderr, nursery-4-gc-diagnostics.stderr, census.jsonl, vmmap-*.txt, and the original/typed-receiver makeTree disassemblies. These paths are local artifacts, not publicly hosted links.

Activity

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