mirror of
https://github.com/tailscale/tailscale.git
synced 2025-01-10 18:13:41 +00:00
70 lines
1.5 KiB
Go
70 lines
1.5 KiB
Go
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||
|
|
||
|
package syncs
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"strconv"
|
||
|
"sync/atomic"
|
||
|
|
||
|
"golang.org/x/sys/cpu"
|
||
|
)
|
||
|
|
||
|
// ShardedInt provides a sharded atomic int64 value that optimizes high
|
||
|
// frequency (Mhz range and above) writes in highly parallel workloads.
|
||
|
// The zero value is not safe for use; use [NewShardedInt].
|
||
|
// ShardedInt implements the expvar.Var interface.
|
||
|
type ShardedInt struct {
|
||
|
sv *ShardValue[intShard]
|
||
|
}
|
||
|
|
||
|
// NewShardedInt returns a new [ShardedInt].
|
||
|
func NewShardedInt() *ShardedInt {
|
||
|
return &ShardedInt{
|
||
|
sv: NewShardValue[intShard](),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Add adds delta to the value.
|
||
|
func (m *ShardedInt) Add(delta int64) {
|
||
|
m.sv.One(func(v *intShard) {
|
||
|
v.Add(delta)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
type intShard struct {
|
||
|
atomic.Int64
|
||
|
_ cpu.CacheLinePad // avoid false sharing of neighboring shards
|
||
|
}
|
||
|
|
||
|
// Value returns the current value.
|
||
|
func (m *ShardedInt) Value() int64 {
|
||
|
var v int64
|
||
|
for s := range m.sv.All {
|
||
|
v += s.Load()
|
||
|
}
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
// GetDistribution returns the current value in each shard.
|
||
|
// This is intended for observability/debugging only.
|
||
|
func (m *ShardedInt) GetDistribution() []int64 {
|
||
|
v := make([]int64, 0, m.sv.Len())
|
||
|
for s := range m.sv.All {
|
||
|
v = append(v, s.Load())
|
||
|
}
|
||
|
return v
|
||
|
}
|
||
|
|
||
|
// String implements the expvar.Var interface
|
||
|
func (m *ShardedInt) String() string {
|
||
|
v, _ := json.Marshal(m.Value())
|
||
|
return string(v)
|
||
|
}
|
||
|
|
||
|
// AppendText implements the encoding.TextAppender interface
|
||
|
func (m *ShardedInt) AppendText(b []byte) ([]byte, error) {
|
||
|
return strconv.AppendInt(b, m.Value(), 10), nil
|
||
|
}
|