Skip to content

fufuok/cmap

Repository files navigation

🌈 Concurrent Map

sync.Map with better read and write performance (supports any type of the key)

forked from orcaman/concurrent-map

For cache, you can choose: Cache/CacheOf and Map/MapOf

✨ Changelog

  • Unified initialization method: cmap.NewOf[K, V](), Used xxhash, thanks.
  • For generics: Optionally specify the number of shards to improve performance.
    • func NewOf[K Hashable, V any](numShards ...int) *MapOf[K, V]
  • Supports both generic and non-generic types.
  • Add benchmarks for commonly used Map packages, See: 🤖 Benchmarks

🔖 Tips

ShardCount can also be specified globally, but it must be executed before all Maps are initialized and cannot be modified.

cmap.ShardCount = 128

⚙️ Installation

go get -u github.com/fufuok/cmap

⚡️ Quickstart

non-generic

package main

import (
	"fmt"

	"github.com/fufuok/cmap"
)

func main() {
	m := cmap.New()
	m.Set("A", 1)
	v := m.Upsert("A", 2, func(exist bool, valueInMap interface{}, newValue interface{}) interface{} {
		if valueInMap == 1 {
			return newValue.(int) + 1
		}
		return 0
	})
	fmt.Println(v)
	fmt.Println(m.Get("A"))
	m.SetIfAbsent("B", 42)
	m.Remove("A")
	fmt.Println(m.Count())
	for item := range m.IterBuffered() {
		fmt.Println(item)
	}
	m.Clear()

	// Output:
	// 3
	// 3 true
	// 1
	// {B 42}
}

generic

package main

import (
	"fmt"

	"github.com/fufuok/cmap"
)

func main() {
	// Specifies the number of shards.
	// m := cmap.NewOf[int, int](128)
	m := cmap.NewOf[int, int]()
	m.Set(1, 1)
	v := m.Upsert(1, 2, func(exist bool, valueInMap int, newValue int) int {
		if valueInMap == 1 {
			return newValue + 1
		}
		return 0
	})
	fmt.Println(v)
	fmt.Println(m.Get(1))
	m.SetIfAbsent(2, 42)
	m.Remove(1)
	fmt.Println(m.Count())
	for item := range m.IterBuffered() {
		fmt.Println(item)
	}
	m.Clear()

	// Output:
	// 3
	// 3 true
	// 1
	// {2 42}
}

custom type

package main

import (
	"fmt"

	"github.com/fufuok/cmap"
)

type Person struct {
	name string
	age  int16
}

func main() {
	hasher := func(p Person) uint64 {
		return uint64(fnv32(p.name))<<32 | uint64(31*p.age)
	}
	m := cmap.NewTypedMapOf[Person, int](hasher)
	m.Set(Person{"ff", 18}, 1)
	v := m.Upsert(Person{"ff", 18}, 2, func(exist bool, valueInMap int, newValue int) int {
		if valueInMap == 1 {
			return newValue + 1
		}
		return 0
	})
	fmt.Println(v)
	fmt.Println(m.Get(Person{"ff", 18}))
	m.SetIfAbsent(Person{"uu", 20}, 42)
	m.Remove(Person{"ff", 18})
	fmt.Println(m.Count())
	for item := range m.IterBuffered() {
		fmt.Println(item)
	}
	m.Clear()

	// Output:
	// 3
	// 3 true
	// 1
	// {{uu 20} 42}
}

func fnv32(key string) uint32 {
	hash := uint32(2166136261)
	const prime32 = uint32(16777619)
	keyLength := len(key)
	for i := 0; i < keyLength; i++ {
		hash *= prime32
		hash ^= uint32(key[i])
	}
	return hash
}

LICENSE

MIT (see LICENSE file)

ff

About

🌈 读写性能更优的 sync.Map. a thread-safe concurrent map for go. forked from orcaman/concurrent-map

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages