Skip to content

Commit

Permalink
Get rid of hash function in MapOf factory functions
Browse files Browse the repository at this point in the history
Also upgrades library version to v3
  • Loading branch information
puzpuzpuz committed Oct 22, 2023
1 parent 92b8269 commit b3a8173
Show file tree
Hide file tree
Showing 24 changed files with 447 additions and 642 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-32-bit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: [1.21.x]
go-version: [1.19.x, 1.20.x, 1.21.x]
name: Build with Go ${{ matrix.go-version }} 32-bit
steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: [1.21.x]
go-version: [1.19.x, 1.20.x, 1.21.x]
name: Build with Go ${{ matrix.go-version }}
steps:
- uses: actions/checkout@v3
Expand Down
28 changes: 9 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[![GoDoc reference](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/puzpuzpuz/xsync/v2)
[![GoReport](https://goreportcard.com/badge/github.com/puzpuzpuz/xsync/v2)](https://goreportcard.com/report/github.com/puzpuzpuz/xsync/v2)
[![GoDoc reference](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/puzpuzpuz/xsync/v3)
[![GoReport](https://goreportcard.com/badge/github.com/puzpuzpuz/xsync/v3)](https://goreportcard.com/report/github.com/puzpuzpuz/xsync/v3)
[![codecov](https://codecov.io/gh/puzpuzpuz/xsync/branch/main/graph/badge.svg)](https://codecov.io/gh/puzpuzpuz/xsync)

# xsync
Expand All @@ -16,15 +16,15 @@ Also, a non-scientific, unfair benchmark comparing Java's [j.u.c.ConcurrentHashM

## Usage

The latest xsync major version is v2, so `/v2` suffix should be used when importing the library:
The latest xsync major version is v3, so `/v3` suffix should be used when importing the library:

```go
import (
"github.com/puzpuzpuz/xsync/v2"
"github.com/puzpuzpuz/xsync/v3"
)
```

*Note for v1 users*: v1 support is discontinued, so please upgrade to v2. While the API has some breaking changes, the migration should be trivial.
*Note for v1 users*: v1 support is discontinued, so please upgrade to v3. While the API has some breaking changes, the migration should be trivial.

### Counter

Expand All @@ -35,7 +35,7 @@ c := xsync.NewCounter()
// increment and decrement the counter
c.Inc()
c.Dec()
// read the current value
// read the current value
v := c.Value()
```

Expand All @@ -58,10 +58,10 @@ CLHT is built around idea to organize the hash table in cache-line-sized buckets

One important difference with `sync.Map` is that only string keys are supported. That's because Golang standard library does not expose the built-in hash functions for `interface{}` values.

`MapOf[K, V]` is an implementation with parametrized value type. It is available for Go 1.18 or later. While it's still a CLHT-inspired hash map, `MapOf`'s design is quite different from `Map`. As a result, less GC pressure and less atomic operations on reads.
`MapOf[K, V]` is an implementation with parametrized value type. While it's still a CLHT-inspired hash map, `MapOf`'s design is quite different from `Map`. As a result, less GC pressure and less atomic operations on reads.

```go
m := xsync.NewMapOf[string]()
m := xsync.NewMapOf[string, string]()
m.Store("foo", "bar")
v, ok := m.Load("foo")
```
Expand All @@ -73,17 +73,7 @@ type Point struct {
x int32
y int32
}
m := NewTypedMapOf[Point, int](func(seed maphash.Seed, p Point) uint64 {
// provide a hash function when creating the MapOf;
// we recommend using the hash/maphash package for the function
var h maphash.Hash
h.SetSeed(seed)
binary.Write(&h, binary.LittleEndian, p.x)
hash := h.Sum64()
h.Reset()
binary.Write(&h, binary.LittleEndian, p.y)
return 31*hash + h.Sum64()
})
m := NewMapOf[Point, int]()
m.Store(Point{42, 42}, 42)
v, ok := m.Load(point{42, 42})
```
Expand Down
4 changes: 2 additions & 2 deletions counter.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (c *Counter) Add(delta int64) {
t, ok := ptokenPool.Get().(*ptoken)
if !ok {
t = new(ptoken)
t.idx = fastrand()
t.idx = runtime_fastrand()
}
for {
stripe := &c.stripes[t.idx&c.mask]
Expand All @@ -71,7 +71,7 @@ func (c *Counter) Add(delta int64) {
break
}
// Give a try with another randomly selected stripe.
t.idx = fastrand()
t.idx = runtime_fastrand()
}
ptokenPool.Put(t)
}
Expand Down
2 changes: 1 addition & 1 deletion counter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"sync/atomic"
"testing"

. "github.com/puzpuzpuz/xsync/v2"
. "github.com/puzpuzpuz/xsync/v3"
)

func TestCounterInc(t *testing.T) {
Expand Down
33 changes: 2 additions & 31 deletions example_test.go
Original file line number Diff line number Diff line change
@@ -1,42 +1,13 @@
//go:build go1.18
// +build go1.18

package xsync_test

import (
"encoding/binary"
"fmt"
"hash/maphash"
"time"

"github.com/puzpuzpuz/xsync/v2"
"github.com/puzpuzpuz/xsync/v3"
)

func ExampleNewTypedMapOf() {
type Person struct {
GivenName string
FamilyName string
YearOfBirth int16
}
age := xsync.NewTypedMapOf[Person, int](func(seed maphash.Seed, p Person) uint64 {
var h maphash.Hash
h.SetSeed(seed)
h.WriteString(p.GivenName)
hash := h.Sum64()
h.Reset()
h.WriteString(p.FamilyName)
hash = 31*hash + h.Sum64()
h.Reset()
binary.Write(&h, binary.LittleEndian, p.YearOfBirth)
return 31*hash + h.Sum64()
})
Y := time.Now().Year()
age.Store(Person{"Ada", "Lovelace", 1815}, Y-1815)
age.Store(Person{"Charles", "Babbage", 1791}, Y-1791)
}

func ExampleMapOf_Compute() {
counts := xsync.NewIntegerMapOf[int, int]()
counts := xsync.NewMapOf[int, int]()

// Store a new value.
v, ok := counts.Compute(42, func(oldValue int, loaded bool) (newValue int, delete bool) {
Expand Down
12 changes: 0 additions & 12 deletions export_mapof_test.go

This file was deleted.

34 changes: 26 additions & 8 deletions export_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package xsync

import "hash/maphash"

const (
EntriesPerMapBucket = entriesPerMapBucket
MapLoadFactor = mapLoadFactor
Expand All @@ -11,7 +9,8 @@ const (
)

type (
BucketPadded = bucketPadded
BucketPadded = bucketPadded
BucketOfPadded = bucketOfPadded
)

type MapStats struct {
Expand Down Expand Up @@ -50,14 +49,33 @@ func DisableAssertions() {
assertionsEnabled = false
}

func HashString(seed maphash.Seed, s string) uint64 {
return hashString(seed, s)
}

func Fastrand() uint32 {
return fastrand()
return runtime_fastrand()
}

func NextPowOf2(v uint32) uint32 {
return nextPowOf2(v)
}

func MakeSeed() uint64 {
return makeSeed()
}

func HashString(s string, seed uint64) uint64 {
return hashString(s, seed)
}

func MakeHasher[T comparable]() func(T, uint64) uint64 {
return makeHasher[T]()
}

func CollectMapOfStats[K comparable, V any](m *MapOf[K, V]) MapStats {
return MapStats{m.stats()}
}

func NewMapOfPresizedWithHasher[K comparable, V any](
hasher func(K, uint64) uint64,
sizeHint int,
) *MapOf[K, V] {
return newMapOfPresized[K, V](hasher, sizeHint)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/puzpuzpuz/xsync/v2
module github.com/puzpuzpuz/xsync/v3

go 1.20
Loading

0 comments on commit b3a8173

Please sign in to comment.