From 338cb1e0004be1af2438674341630592c465e80e Mon Sep 17 00:00:00 2001 From: Yonah Date: Sun, 22 Mar 2026 22:22:04 +0900 Subject: [PATCH] ident: system identifier generator This is pretty fast and guarantees uniqueness when initialised correctly. Signed-off-by: Yonah --- ident/ident.go | 47 ++++++++++++++++++++++++++++++++++++++++++++ ident/ident_test.go | 28 ++++++++++++++++++++++---- ident/member_test.go | 6 ++++-- ident/system.go | 8 ++------ ident/system_test.go | 6 ++++-- 5 files changed, 81 insertions(+), 14 deletions(-) diff --git a/ident/ident.go b/ident/ident.go index e00d6ca..c432fd2 100644 --- a/ident/ident.go +++ b/ident/ident.go @@ -6,7 +6,10 @@ import ( "encoding" "errors" "fmt" + "math/rand/v2" "strconv" + "sync" + "time" "unsafe" ) @@ -97,3 +100,47 @@ func (full *F[V, T]) UnmarshalText(data []byte) (err error) { } return full.Remote.UnmarshalText(data[sz+1:]) } + +// PartG is machine-specific state of [Generator]. +type PartG struct { + // Deployment site, typically denoting a datacenter servicing a region. + Site uint32 + // Servicing host behind load balancer, unique within its Site. + Host uint32 +} + +// A Generator emits unique instances of [S]. +type Generator struct { + PartG + mu sync.Mutex + r rand.Source +} + +// S populates the value pointed to by p with a new unique value. +func (g *Generator) S(p *S) { + g.mu.Lock() + *p = S{PartG: g.PartG, Time: uint64(time.Now().UnixNano()), ID: g.r.Uint64()} + g.mu.Unlock() +} + +// NewS creates a unique instance of [S] and returns its address. +func (g *Generator) NewS() *S { + var sid S + g.S(&sid) + return &sid +} + +// M populates the value pointed to by p with a new unique value. +func (g *Generator) M(p *PartM, serial uint64) { + g.mu.Lock() + *p = PartM{Serial: serial, Time: uint64(time.Now().UnixNano()), ID: g.r.Uint64()} + g.mu.Unlock() +} + +// New initialises a new instance of [Generator] and returns its address. +func New(site, host uint32) *Generator { + return &Generator{PartG{site, host}, sync.Mutex{}, rand.NewPCG( + uint64(site)<<32|uint64(host), + uint64(time.Now().UnixNano()), + )} +} diff --git a/ident/ident_test.go b/ident/ident_test.go index f49edca..09f4ee8 100644 --- a/ident/ident_test.go +++ b/ident/ident_test.go @@ -89,8 +89,10 @@ func TestFS(t *testing.T) { {"valid", ident.F[ident.S, *ident.S]{ I: &ident.S{ - Site: ident.TrivialSite, - Host: ident.TrivialHost, + PartG: ident.PartG{ + Site: ident.TrivialSite, + Host: ident.TrivialHost, + }, Time: uint64(time.Date( 0xfd, 7, 15, @@ -130,8 +132,10 @@ func TestFM(t *testing.T) { }, System: ident.S{ - Site: ident.TrivialSite, - Host: ident.TrivialHost, + PartG: ident.PartG{ + Site: ident.TrivialSite, + Host: ident.TrivialHost, + }, Time: uint64(time.Date( 0xfd, 7, 15, @@ -207,3 +211,19 @@ func TestErrors(t *testing.T) { }) } } + +func BenchmarkGeneratorS(b *testing.B) { + var s ident.S + g := ident.New(ident.TrivialSite, ident.TrivialHost) + for b.Loop() { + g.S(&s) + } +} + +func BenchmarkGeneratorM(b *testing.B) { + var pm ident.PartM + g := ident.New(ident.TrivialSite, ident.TrivialHost) + for b.Loop() { + g.M(&pm, 0xbadf00d) + } +} diff --git a/ident/member_test.go b/ident/member_test.go index fd04662..3c9f76d 100644 --- a/ident/member_test.go +++ b/ident/member_test.go @@ -98,8 +98,10 @@ func TestM(t *testing.T) { }, System: ident.S{ - Site: ident.TrivialSite, - Host: ident.TrivialHost, + PartG: ident.PartG{ + Site: ident.TrivialSite, + Host: ident.TrivialHost, + }, Time: uint64(time.Date( 0xfd, 7, 15, diff --git a/ident/system.go b/ident/system.go index c8d2b97..8328eaf 100644 --- a/ident/system.go +++ b/ident/system.go @@ -17,17 +17,13 @@ const ( // S represents a unique system identifier. type S struct { - // Deployment site, typically denoting a datacenter servicing a region. - Site uint32 - // Servicing host behind load balancer, unique within its Site. - Host uint32 - + PartG // An instant in time, some time after the corresponding system metadata // first appeared to the backend, represented in nanoseconds since // 1970-01-01. Time uint64 // Randomly generated value. The implementation must guarantee that the same - // value cannot be emitted for a Time value on a servicing Host. + // value cannot be emitted for a Time value on a servicing host. ID uint64 } diff --git a/ident/system_test.go b/ident/system_test.go index 2e8f68b..07e2fc7 100644 --- a/ident/system_test.go +++ b/ident/system_test.go @@ -34,8 +34,10 @@ func TestS(t *testing.T) { ), ident.ErrNewline}, {"valid", ident.S{ - Site: ident.TrivialSite, - Host: ident.TrivialHost, + PartG: ident.PartG{ + Site: ident.TrivialSite, + Host: ident.TrivialHost, + }, Time: uint64(time.Date( 0xfd, 7, 15,