chore: import upstream snapshot with attribution
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
// Package intern provides a process-wide string interning table.
|
||||
//
|
||||
// The knowledge graph stores a node's ID once on the node, but also
|
||||
// once on every edge endpoint that references it, and a file path once
|
||||
// per node defined in that file. Under a multi-repo warmup those
|
||||
// references are minted as fresh `repoPrefix + "/" + id` concatenations
|
||||
// — a heap profile attributed ~425 MB of resident memory to that
|
||||
// concatenation alone. Interning collapses every duplicate of a string
|
||||
// to a single shared backing array.
|
||||
//
|
||||
// The table is process-global and never shrinks: an interned string
|
||||
// lives until process exit even if every repo referencing it is later
|
||||
// evicted. This is a deliberate trade — node IDs and file paths are
|
||||
// low-cardinality and heavily duplicated, so the bounded table costs
|
||||
// far less than the duplication it removes.
|
||||
package intern
|
||||
|
||||
import "sync"
|
||||
|
||||
// shardCount fans interning lookups across independent locks so the
|
||||
// parallel warmup workers (one goroutine per repo) do not serialise on
|
||||
// a single mutex. 64 keeps per-shard maps small without waste.
|
||||
const shardCount = 64
|
||||
|
||||
type shard struct {
|
||||
mu sync.RWMutex
|
||||
m map[string]string
|
||||
}
|
||||
|
||||
var shards [shardCount]*shard
|
||||
|
||||
func init() {
|
||||
for i := range shards {
|
||||
shards[i] = &shard{m: make(map[string]string)}
|
||||
}
|
||||
}
|
||||
|
||||
// shardFor picks a shard by FNV-1a hash of s — inlined rather than
|
||||
// using hash/fnv to avoid a hash-object allocation on every call.
|
||||
func shardFor(s string) *shard {
|
||||
var h uint32 = 2166136261
|
||||
for i := 0; i < len(s); i++ {
|
||||
h ^= uint32(s[i])
|
||||
h *= 16777619
|
||||
}
|
||||
return shards[h%shardCount]
|
||||
}
|
||||
|
||||
// String returns the canonical instance of s. Every call with an equal
|
||||
// string returns the same backing array, so the caller may drop its
|
||||
// own copy. The empty string is returned as-is without touching the
|
||||
// table. Safe for concurrent use.
|
||||
func String(s string) string {
|
||||
if s == "" {
|
||||
return ""
|
||||
}
|
||||
sh := shardFor(s)
|
||||
sh.mu.RLock()
|
||||
c, ok := sh.m[s]
|
||||
sh.mu.RUnlock()
|
||||
if ok {
|
||||
return c
|
||||
}
|
||||
sh.mu.Lock()
|
||||
if c, ok = sh.m[s]; !ok {
|
||||
sh.m[s] = s
|
||||
c = s
|
||||
}
|
||||
sh.mu.Unlock()
|
||||
return c
|
||||
}
|
||||
|
||||
// Len reports the number of distinct strings currently interned.
|
||||
// Intended for diagnostics and tests.
|
||||
func Len() int {
|
||||
n := 0
|
||||
for _, sh := range shards {
|
||||
sh.mu.RLock()
|
||||
n += len(sh.m)
|
||||
sh.mu.RUnlock()
|
||||
}
|
||||
return n
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package intern
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// backing returns the address of a string's backing array, so two
|
||||
// strings can be checked for *sharing storage* rather than just being
|
||||
// byte-equal.
|
||||
func backing(s string) uintptr {
|
||||
return uintptr(unsafe.Pointer(unsafe.StringData(s)))
|
||||
}
|
||||
|
||||
func TestString_EqualInputsShareBacking(t *testing.T) {
|
||||
// Two independently-allocated but equal strings.
|
||||
a := fmt.Sprintf("repo/%s", "pkg/foo.go::Bar")
|
||||
b := fmt.Sprintf("repo/%s", "pkg/foo.go::Bar")
|
||||
if backing(a) == backing(b) {
|
||||
t.Fatal("test setup: a and b unexpectedly already share storage")
|
||||
}
|
||||
ia := String(a)
|
||||
ib := String(b)
|
||||
if ia != ib {
|
||||
t.Fatalf("interned values differ: %q vs %q", ia, ib)
|
||||
}
|
||||
if backing(ia) != backing(ib) {
|
||||
t.Fatal("interned equal strings do not share a backing array")
|
||||
}
|
||||
}
|
||||
|
||||
func TestString_Empty(t *testing.T) {
|
||||
if got := String(""); got != "" {
|
||||
t.Fatalf("String(\"\") = %q, want empty", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestString_DistinctInputsDistinctValues(t *testing.T) {
|
||||
if String("alpha") == String("beta") {
|
||||
t.Fatal("distinct strings interned to the same value")
|
||||
}
|
||||
}
|
||||
|
||||
// TestString_Concurrent races many goroutines interning an overlapping
|
||||
// set of strings. Run under -race; also asserts every goroutine agrees
|
||||
// on one canonical backing array per value.
|
||||
func TestString_Concurrent(t *testing.T) {
|
||||
const workers = 32
|
||||
const keys = 64
|
||||
var wg sync.WaitGroup
|
||||
results := make([]uintptr, workers)
|
||||
for w := 0; w < workers; w++ {
|
||||
wg.Add(1)
|
||||
go func(w int) {
|
||||
defer wg.Done()
|
||||
var last uintptr
|
||||
for i := 0; i < keys; i++ {
|
||||
s := String(fmt.Sprintf("concurrent/key/%d", i))
|
||||
if i == keys/2 {
|
||||
last = backing(s)
|
||||
}
|
||||
}
|
||||
results[w] = last
|
||||
}(w)
|
||||
}
|
||||
wg.Wait()
|
||||
for w := 1; w < workers; w++ {
|
||||
if results[w] != results[0] {
|
||||
t.Fatalf("worker %d saw a different backing array for the same key", w)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user