> ## Content Index
> Fetch the complete content index at: https://huizhou92.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Swiss Map in Go 1.24: Compatibility, Extendible Hashing, and Legacy Issues
- URL: https://huizhou92.com/swiss-map-in-go-1-24-compatibility-extendible-hashing-and-legacy-issues/
- Published: 2025-01-23T07:22:42.000Z
- Updated: 2026-09-08T02:29:17.000Z
- Description: Swiss Map in Go 1.24: Compatibility, Extendible Hashing, and Legacy Issues. In the previous article , I introduced swiss map and a Go implementation by Dol。
- Author: huizhou92
- Tags: #Migrated-1788833207488, #Import 2026-09-08 02:07

In the [previous article](https://pub.huizhou92.com/swisstable-a-high-performance-hash-table-implementation-3e13bfe8c79b?ref=huizhou92.com), I introduced `swiss map` and a Go implementation by Dolthub. Readers unfamiliar with `swiss map` should review that piece first.

[SwissTable: A High-Performance Hash Table ImplementationWill it become the standard library for Go map?![](https://huizhou92.com/content/images/2026/09/0-kkefkphnhfmamyap.jpg)](https://pub.huizhou92.com/swisstable-a-high-performance-hash-table-implementation-3e13bfe8c79b?ref=huizhou92.com)

With the upcoming release of Go 1.24 `swiss map` will replace the existing `map` implementation in the Go standard library. It maintains full API compatibility while delivering over 50% performance improvements in specific benchmark scenarios. Currently, `swiss map` is my most anticipated feature in Go 1.24\. But does it truly live up to the hype? This article analyzes its core design through three lenses: **compatibility**, **Extensible Hashing implementation**, and **remaining challenges**.

### Compatibility: Seamless Migration Support

One of `swiss map`'s key design goals is backward compatibility with Go's legacy `map`. Conditional compilation flags and type conversions enable zero-code migration. For example, in `export_swiss_test.go`, the `newTestMapType` function directly converts legacy `map` metadata into `swiss map`'s type structure:

```go
// https://github.com/golang/go/blob/3f4164f508b8148eb526fc096884dba2609f5835/src/internal/runtime/maps/export_swiss_test.go#L14 
func newTestMapType[K comparable, V any]() *abi.SwissMapType { 
    var m map[K]V 
    mTyp := abi.TypeOf(m) 
    mt := (*abi.SwissMapType)(unsafe.Pointer(mTyp)) // Direct type conversion 
    return mt 
}
```

This design allows existing code to enable `swiss map` via the experimental flag `GOEXPERIMENT=swissmap` (now enabled by default in gotip builds like `go1.24-3f4164f5`). To revert to the legacy map implementation, use `GOEXPERIMENT=noswissmap`.

### Swiss Map’s Data Structure

![Swiss Map’s Data Structure](https://huizhou92.com/content/images/2026/09/0-ovo6fjkdjod9qcvt.png)

### Extendible Hashing: Efficient Incremental Scaling

Beyond compatibility improvements, `swiss map` introduces **Extensible Hashing** to enable efficient incremental scaling. Unlike traditional hash tables, which require complete data migration during resizing, Extensible Hashing distributes scaling costs across multiple operations using multi-level directories and table splitting.

#### Directory and Table Hierarchy

The `Map` struct in `map.go` uses `globalDepth` and `directory` to manage hierarchy:

```go
// https://github.com/golang/go/blob/3f4164f508b8148eb526fc096884dba2609f5835/src/internal/runtime/maps/map.go#L194 
type Map struct { 
    globalDepth  uint8       // Global depth of directory 
    dirPtr       unsafe.Pointer // Pointer to directory (array of tables) 
    // ... 
}
```

The directory size is `1 << globalDepth`, with each entry pointing to a `table`. When a table reaches its capacity (`maxTableCapacity`, default 1024), it triggers a **split** instead of global resizing.

#### Split Operation

A split creates two child tables (`left` and `right`) with increased `localDepth`, redistributing data based on hash bits:

```go
// https://github.com/golang/go/blob/3f4164f508b8148eb526fc096884dba2609f5835/src/internal/runtime/maps/table.go#L1043 
func (t *table) split(typ *abi.SwissMapType, m *Map) { 
    localDepth := t.localDepth 
    localDepth++ // Child tables have +1 local depth 
    left := newTable(typ, maxTableCapacity, -1, localDepth) 
    right := newTable(typ, maxTableCapacity, -1, localDepth) 
    // ... 
}
```

New tables allocate contiguous memory blocks via `newarray`, preserving cache locality.

#### Data Redistribution: Hash Masking

During splits, hash values’ high-order bits (determined by `localDepth`) dictate data placement:

```go
// https://github.com/golang/go/blob/3f4164f508b8148eb526fc096884dba2609f5835/src/internal/runtime/maps/table.go#L1052 
mask := localDepthMask(localDepth) // e.g., 0x80000000 (32-bit) 
for ... { 
    hash := typ.Hasher(key, m.seed) 
    if hash & mask == 0 { 
        left.uncheckedPutSlot(...) // Assign to left table 
    } else { 
        right.uncheckedPutSlot(...) // Assign to right table 
    } 
}
```

- **Mask Calculation**: `localDepthMask` generates masks like:  
 \- `localDepth=1` → `0x80000000` (32-bit) or `0x8000000000000000` (64-bit)

#### Directory Expansion

When a split occurs at the global depth, the directory doubles in size:

```go
// map.go 
func (m *Map) installTableSplit(old, left, right *table) { 
    if old.localDepth == m.globalDepth { 
        newDir := make([]*table, m.dirLen*2) // Double directory size 
        // Update directory entries... 
        m.globalDepth++ 
    } 
    // ... 
}
```

**Example: Directory Expansion**  
Initial state (`globalDepth=1`):

```none
directory[0] → Table A (localDepth=1) 
directory[1] → Table A (localDepth=1)
```

After split (`globalDepth=2`):

```none
directory[0] → Left  (hash prefix 00) 
directory[1] → Left  (hash prefix 01) 
directory[2] → Right (hash prefix 10) 
directory[3] → Right (hash prefix 11)
```

#### Key Advantages

1. **Locality**: Only overloaded tables split
2. **Incremental Scaling**: Directory grows on demand
3. **Cache Efficiency**: Continuous memory allocation for table groups

### Additional Optimizations

`swiss map` optimizes small-element scenarios (≤8 elements) using a single group, minimizing performance penalties for small datasets.

### Remaining Challenges

Despite significant improvements, several issues remain:

#### Concurrency Limitations

The current implementation uses a simple `writing` flag for concurrent write detection:

```go
// https://github.com/golang/go/blob/3f4164f508b8148eb526fc096884dba2609f5835/src/internal/runtime/maps/map.go#L478 
func (m *Map) PutSlot(typ *abi.SwissMapType, key unsafe.Pointer) unsafe.Pointer { 
    m.writing ^= 1 // Non-atomic flag 
    // ... 
}
```

This may cause race conditions in high-concurrency scenarios. Future versions may introduce finer-grained locking.

#### Memory Fragmentation

The `group` structure (8 control bytes + 8 key-value slots) may waste memory for small types. For example, `int32` keys with `int8` values leave 3 bytes unused per slot.

#### Iterator Complexity

The `Iter` implementation handles directory expansion and table splits, adding complexity:

```go
// https://github.com/golang/go/blob/3f4164f508b8148eb526fc096884dba2609f5835/src/internal/runtime/maps/table.go#L742 
func (it *Iter) Next() { 
    if it.globalDepth != it.m.globalDepth { 
        // Handle directory expansion 
        it.dirIdx <<= (it.m.globalDepth - it.globalDepth) 
    } 
    // ... 
}
```

Frequent resizing may impact iterator performance.

Additionally, numerous TODOs remain in the latest codebase (see the image below), and questions about their resolution remain unresolved before Go 1.24’s release.

![More TODO in maps src](https://huizhou92.com/content/images/2026/09/0-fso8bqa04tppjf4x.png)

Community discussions highlight performance variability, with some reports of regressions

![More issue by swiss map](https://huizhou92.com/content/images/2026/09/1-btjqzvvfrikev1xbzjdixg.png)

[https://github.com/golang/go/issues?q=is%3Aissue%20state%3Aopen%20swiss](https://github.com/golang/go/issues?q=is%3Aissue%20state%3Aopen%20swiss&ref=huizhou92.com)

### Performance Testing

Test code: [github.com/hxzhouh/gomapbench](https://github.com/hxzhouh/gomapbench?ref=huizhou92.com)

gotip version: `go version devel go1.24-3f4164f5 Mon Jan 20 09:25:11 2025 -0800 darwin/arm64`   
Environment: Mac Book M1 Pro. No SIMD

![Average performance improvements hover around 27.9%, with some scenarios showing up to 50% gains.](https://huizhou92.com/content/images/2026/09/1-ygrgjbjtb4qszrlernb-la.png)

Average performance improvements hover around 27.9%, with some scenarios showing up to 50% gains.

However, these results are machine-specific, and some users report performance regressions. The final evaluation awaits further optimization.

### Conclusion

Go 1.24’s `swiss map` delivers significant performance gains through compatibility design, Extendible Hashing, and optimized probing sequences.   
However, challenges remain in concurrency handling and memory efficiency. Developers should consider adopting it in performance-critical contexts while monitoring its evolving implementation.

### References

- [Tony Bai’s Analysis](https://tonybai.com/2024/11/14/go-map-use-swiss-table/?ref=huizhou92.com)
- [GitHub Issue #54766](https://github.com/golang/go/issues/54766?ref=huizhou92.com)
- [Extendible Hashing Explained](https://www.geeksforgeeks.org/extendible-hashing-dynamic-approach-to-dbms/?ref=huizhou92.com)
- [Original Implementation Article](https://pub.huizhou92.com/swisstable-a-high-performance-hash-table-implementation-3e13bfe8c79b?ref=huizhou92.com)