datadog

How Go 1.24's Swiss Tables saved us hundreds of gigabytes | Datadog (opens in new tab)

Datadog’s article explains how Swiss Tables provide a faster and more memory-efficient hash-table design for Go. The approach replaces traditional bucket-based lookup with compact control metadata and group probing, allowing the runtime to reject non-matching entries quickly. The article concludes that Swiss Tables can improve map performance and memory usage, while requiring careful attention to compatibility, implementation complexity, and workload-specific benchmarking.

Why Traditional Go Maps Have Limitations

  • Conventional hash tables organize entries into buckets and may require several memory accesses during lookup.
  • As maps grow, collisions and overflow buckets can increase lookup costs.
  • Pointer-heavy layouts also add memory overhead and reduce cache locality.
  • These costs matter for Datadog workloads that maintain large numbers of maps containing metrics, tags, and other high-cardinality data.

How Swiss Tables Work

  • Swiss Tables store compact metadata alongside groups of key-value slots.
  • Each entry’s hash is divided into:
    • A portion used to select the initial table location.
    • A short fingerprint stored in control metadata.
  • Lookups compare fingerprints across multiple slots before examining full keys.
  • Empty and deleted markers in the metadata make it possible to skip large portions of the table quickly.
  • Group-oriented probing improves cache locality and reduces the number of key comparisons.

Adapting the Design to Go

  • A Go implementation must account for Go-specific features such as:
    • Garbage collection.
    • Generic types.
    • Interface and pointer representations.
    • Map growth and deletion semantics.
  • The implementation needs to preserve expected Go map behavior while changing the underlying storage strategy.
  • Careful handling of memory layout is essential because metadata, keys, values, and garbage-collector scanning all affect performance.

Performance and Memory Trade-offs

  • Swiss Tables can reduce memory overhead by storing compact fingerprints instead of repeatedly examining full keys.
  • Better locality can improve lookup and insertion speed, particularly for large maps.
  • Results depend on factors such as:
    • Map size.
    • Key and value types.
    • Read/write ratios.
    • Collision rates.
    • Frequency of growth and deletion.
  • Benchmarks are therefore necessary before replacing an existing map implementation in production.

Practical Lessons

  • Data-structure improvements should be evaluated against real application workloads, not only synthetic benchmarks.
  • Memory layout and garbage-collector behavior can be as important as algorithmic complexity.
  • Swiss Tables are a promising foundation for efficient Go maps, but their advantages must be balanced against implementation complexity and compatibility requirements.

Datadog’s recommendation is to use Swiss Table techniques where map performance or memory usage is a meaningful bottleneck, and to validate the change with representative benchmarks and production measurements.