Introduction
Hi everyone,
I’ve been exploring the practical implications of the recent paper “Optimal Bounds for Open Addressing Without Reordering” (Farach-Colton et al., arXiv:2501.02305, Jan 2025). I’ve developed a Proof-of-Concept C-extension for Python called DenseDict that implements Elastic Hashing to address the memory overhead inherent in CPython’s power-of-two resizing strategy.
The Problem
Currently, CPython’s dict doubles its capacity when it reaches a load factor of ≈66%. This leads to significant memory waste immediately after a resize, where up to 50% of allocated slots remain empty. Furthermore, these geometric resizes cause latency spikes (“stop-the-world” copies) that can be problematic for real-time or large-scale applications.
The Proposal: Elastic (Funnel) Hashing
DenseDict uses a multi-level funnel strategy with Lazy Level Allocation. Instead of one giant table that doubles in size, it uses geometrically shrinking levels (50%, 25%, 12.5%, etc.) and a dynamic probe limit per level.
Key Advantages:
-
High Load Factor: Operates comfortably at 85-95% load without search degradation.
-
No Reordering: Keys never move once placed, maintaining pointer stability (vital for CPython internals).
-
Predictable Insertion: Eliminates the massive latency spikes associated with doubling the table size.
Benchmark Results (900K Items)
I’ve conducted extensive benchmarks comparing DenseDict v2 against the built-in dict.
| Metric | DenseDict v2 | CPython dict | Improvement |
|---|---|---|---|
| Memory (Integer Keys) | 23.25 MB | 40.00 MB | 41.9% Savings |
| Memory (String Keys) | 23.25 MB | 29.33 MB | 20.7% Savings |
| Avg. Levels/Lookup | 1.648 | N/A | High Density |
| Insert Degradation | +5.6% | +20.1% | More Stable |
| Lookup Performance | 4.27M ops/s | 4.31M ops/s | ~1.1% Difference |
Note: Lookup performance is within 1% of CPython’s highly optimized implementation, while using significantly less RAM.
Interactive Proof-of-Concept
I have prepared a Google Colab and a GitHub Repository where these results can be reproduced:
-
Colab: Google Colab
Discussion
I believe this approach could be particularly beneficial for:
-
FrozenDicts / Immutable mappings: Where high density is a priority.
-
Memory-constrained environments: (e.g., embedded Python or micro-containers).
-
Large-scale caches: Where the 20-40% memory saving translates to gigabytes of reduced overhead.
I’d love to hear the thoughts of the community and the dictobject.c maintainers on whether a multi-level funnel approach could be integrated as a specialized internal representation for high-density dictionaries.
Best regards