Documentation
¶
Overview ¶
Package goshard provides a high-performance, concurrent-safe sharded map.
It is designed to minimize lock contention in high-throughput environments by distributing entries across multiple independent shards, each with its own RWMutex. This approach significantly outperforms a single sync.RWMutex for write-heavy workloads and scales better with the number of CPU cores.
Index ¶
- type ComparableMap
- type Map
- func (sm *Map[K, V]) All() iter.Seq2[K, V]
- func (sm *Map[K, V]) Clear()
- func (sm *Map[K, V]) CompareAndDelete(key K, old V, eq func(current, old V) bool) (deleted bool)
- func (sm *Map[K, V]) CompareAndSwap(key K, old, new V, eq func(current, old V) bool) (swapped bool)
- func (sm *Map[K, V]) Compute(key K, f func(key K, current V, loaded bool) (next V, keep bool)) (value V, loaded bool)
- func (sm *Map[K, V]) Delete(key K)
- func (sm *Map[K, V]) DeleteMany(keys []K)
- func (sm *Map[K, V]) Empty() bool
- func (sm *Map[K, V]) GobDecode(bs []byte) error
- func (sm *Map[K, V]) GobEncode() ([]byte, error)
- func (sm *Map[K, V]) Len() int
- func (sm *Map[K, V]) Load(key K) (value V, ok bool)
- func (sm *Map[K, V]) LoadAndDelete(key K) (value V, loaded bool)
- func (sm *Map[K, V]) LoadAndDeleteMany(keys []K, f func(K, V))
- func (sm *Map[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool)
- func (sm *Map[K, V]) Range(yield func(K, V) bool)
- func (sm *Map[K, V]) Store(key K, value V)
- func (sm *Map[K, V]) Swap(key K, value V) (previous V, loaded bool)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ComparableMap ¶
type ComparableMap[K comparable, V comparable] struct { Map[K, V] }
ComparableMap is a Map with specialized atomic operations for comparable values.
Example (CompareAndDelete) ¶
ExampleComparableMap_compareAndDelete demonstrates deleting a key only when its value matches the expected one.
package main
import (
"fmt"
"github.com/darxnet/goshard"
)
func main() {
m := goshard.NewComparableMap[string, int](0)
m.Store("session", 42)
fmt.Println(m.CompareAndDelete("session", 0)) // wrong value — no-op
fmt.Println(m.CompareAndDelete("session", 42)) // matches — deleted
_, ok := m.Load("session")
fmt.Println(ok)
}
Output: false true false
Example (CompareAndSwap) ¶
ExampleComparableMap_compareAndSwap demonstrates the lock-free-style compare-and-swap for comparable values.
package main
import (
"fmt"
"github.com/darxnet/goshard"
)
func main() {
m := goshard.NewComparableMap[string, string](0)
m.Store("status", "idle")
// Succeeds: current value matches "idle".
fmt.Println(m.CompareAndSwap("status", "idle", "busy"))
// Fails: current value is "busy", not "idle".
fmt.Println(m.CompareAndSwap("status", "idle", "busy"))
}
Output: true false
func NewComparableMap ¶
func NewComparableMap[K comparable, V comparable](n int) *ComparableMap[K, V]
NewComparableMap returns a sharded map for comparable values. If n is zero, NewComparableMap chooses a concurrency-oriented default; otherwise n is rounded up to the next power of two.
func (*ComparableMap[K, V]) CompareAndDelete ¶
func (sm *ComparableMap[K, V]) CompareAndDelete(key K, old V) (deleted bool)
CompareAndDelete deletes the entry for key if its value is equal to old.
func (*ComparableMap[K, V]) CompareAndSwap ¶
func (sm *ComparableMap[K, V]) CompareAndSwap(key K, old, new V) (swapped bool)
CompareAndSwap swaps the old and new values for key if the value stored in the map is equal to old.
type Map ¶
type Map[K comparable, V any] struct { // contains filtered or unexported fields }
Map is a concurrent-safe sharded map optimized for reduced lock contention compared to a Go map paired with a sync.RWMutex.
The zero Map is empty and ready for use. A Map must not be copied after first use.
Example ¶
ExampleMap demonstrates basic store, load, and delete operations.
package main
import (
"fmt"
"github.com/darxnet/goshard"
)
func main() {
m := goshard.NewMap[string, int](0)
m.Store("active_users", 1024)
if v, ok := m.Load("active_users"); ok {
fmt.Println(v)
}
m.Delete("active_users")
if _, ok := m.Load("active_users"); !ok {
fmt.Println("gone")
}
}
Output: 1024 gone
Example (Compute) ¶
ExampleMap_compute demonstrates an atomic read-modify-write under the shard lock — safe to call concurrently.
package main
import (
"fmt"
"github.com/darxnet/goshard"
)
func main() {
m := goshard.NewMap[string, int](0)
m.Store("counter", 0)
m.Compute("counter", func(_ string, current int, loaded bool) (next int, keep bool) {
return current + 1, true
})
v, _ := m.Load("counter")
fmt.Println(v)
}
Output: 1
Example (DeleteMany) ¶
ExampleMap_deleteMany demonstrates efficient batch deletion. Keys are sorted by shard internally to minimise lock acquisitions.
package main
import (
"fmt"
"github.com/darxnet/goshard"
)
func main() {
m := goshard.NewMap[string, int](0)
m.Store("s1", 1)
m.Store("s2", 2)
m.Store("s3", 3)
m.DeleteMany([]string{"s1", "s2", "s3"})
fmt.Println(m.Empty())
}
Output: true
Example (GobEncode) ¶
ExampleMap_gobEncode demonstrates encoding a map to bytes and decoding it back into a new map using encoding/gob.
package main
import (
"fmt"
"github.com/darxnet/goshard"
)
func main() {
src := goshard.NewMap[string, int](0)
src.Store("a", 1)
data, err := src.GobEncode()
if err != nil {
panic(err)
}
dst := goshard.NewMap[string, int](0)
if err := dst.GobDecode(data); err != nil {
panic(err)
}
v, ok := dst.Load("a")
fmt.Println(v, ok)
}
Output: 1 true
Example (LoadOrStore) ¶
ExampleMap_loadOrStore demonstrates get-or-set semantics: the first call stores the value, the second returns the existing one.
package main
import (
"fmt"
"github.com/darxnet/goshard"
)
func main() {
m := goshard.NewMap[string, int](0)
actual, loaded := m.LoadOrStore("limit", 100)
fmt.Println(actual, loaded) // stored
actual, loaded = m.LoadOrStore("limit", 999)
fmt.Println(actual, loaded) // existing value returned
}
Output: 100 false 100 true
Example (Zero) ¶
ExampleMap_zero shows that the zero value of Map is ready to use — no constructor call required.
package main
import (
"fmt"
"github.com/darxnet/goshard"
)
func main() {
var m goshard.Map[string, int]
m.Store("score", 42)
v, ok := m.Load("score")
fmt.Println(v, ok)
}
Output: 42 true
func NewMap ¶
func NewMap[K comparable, V any](n int) *Map[K, V]
NewMap returns a sharded map with n shards. If n is zero, NewMap chooses a concurrency-oriented default; otherwise n is rounded up to the next power of two.
func (*Map[K, V]) All ¶
All returns an iterator over each key and value present in the map.
The iterator does not necessarily correspond to any consistent snapshot of the Map's contents: no key will be visited more than once, but if the value for any key is stored or deleted concurrently (including by yield), the iterator may reflect any mapping for that key from any point during iteration. The iterator does not block other methods on the receiver; even yield itself may call any method on the Map.
func (*Map[K, V]) CompareAndDelete ¶
CompareAndDelete deletes the entry for key if its value is equal to old according to the eq function. The eq function is called while the shard for the key is locked.
func (*Map[K, V]) CompareAndSwap ¶
CompareAndSwap swaps the old and new values for a key if the value stored in the map is equal to old according to the eq function. The eq function is called while the shard for the key is locked.
func (*Map[K, V]) Compute ¶
func (sm *Map[K, V]) Compute(key K, f func(key K, current V, loaded bool) (next V, keep bool)) (value V, loaded bool)
Compute replaces or deletes the value for a key using f. If f returns keep=false, the key is deleted. The function f is called while the key's shard is locked.
func (*Map[K, V]) DeleteMany ¶
func (sm *Map[K, V]) DeleteMany(keys []K)
DeleteMany deletes each key in keys from the map.
func (*Map[K, V]) GobDecode ¶
GobDecode merges gob-encoded shard maps into the map. It applies each decoded gob map immediately, so malformed input can leave earlier decoded entries merged before GobDecode returns an error.
func (*Map[K, V]) GobEncode ¶
GobEncode encodes all non-empty map shards as a sequence of gob maps. Empty shards are skipped; GobDecode reads until EOF and handles a variable number of encoded maps correctly.
func (*Map[K, V]) Load ¶
Load returns the value stored in the map for a key, or the zero value if no value is present. The ok result indicates whether value was found in the map.
func (*Map[K, V]) LoadAndDelete ¶
LoadAndDelete deletes the value for a key, returning the previous value if any. The loaded result reports whether the key was present.
func (*Map[K, V]) LoadAndDeleteMany ¶
func (sm *Map[K, V]) LoadAndDeleteMany(keys []K, f func(K, V))
LoadAndDeleteMany deletes each key in keys from the map and calls f with each key/value pair that was present. The function f is called after the key's shard lock is released.
func (*Map[K, V]) LoadOrStore ¶
LoadOrStore returns the existing value for the key if present. Otherwise, it stores and returns the given value. The loaded result is true if the value was loaded, false if stored.
func (*Map[K, V]) Range ¶
Range calls f sequentially for each key and value present in the map. If f returns false, range stops the iteration.
This exists for compatibility with sync.Map; All should be preferred.