Snawoot / lfmap

Generic concurrent lock-free map for Golang
MIT License
42 stars 1 forks source link

Benchmarks #1

Closed joetifa2003 closed 2 months ago

joetifa2003 commented 2 months ago

Hi, really like your stuff!

I did a benchmark for you map implementation

import (
    "math/rand/v2"
    "sync"
    "testing"

    "github.com/Snawoot/lfmap"
)

// goos: linux
// goarch: amd64
// pkg: github.com/joetifa2003/conc-map/mapcustom
// cpu: AMD Ryzen 7 5800H with Radeon Graphics
// BenchmarkLFMap-16            865           1445544 ns/op         3213814 B/op      27781 allocs/op
// BenchmarkSync-16            1887            653815 ns/op          175533 B/op       4147 allocs/op
const GOROUTINES = 100

const ITERATIONS = 10

func benchPar[T any](b *testing.B, factory func() T, f func(b *testing.B, m T)) {
    for range b.N {
        m := factory()
        var wg sync.WaitGroup
        for range GOROUTINES {
            wg.Add(1)
            go func() {
                defer wg.Done()
                f(b, m)
            }()
        }
        wg.Wait()
    }
}

func BenchmarkLFMap(b *testing.B) {
    benchPar(b,
        func() *lfmap.Map[int, int] { return lfmap.New[int, int]() },
        func(b *testing.B, m *lfmap.Map[int, int]) {
            for i := 0; i < ITERATIONS; i++ {
                m.Set(rand.Int(), i)
            }
        },
    )
}

func BenchmarkSync(b *testing.B) {
    benchPar(b,
        func() *sync.Map { return &sync.Map{} },
        func(b *testing.B, m *sync.Map) {
            for i := 0; i < ITERATIONS; i++ {
                m.Store(rand.Int(), i)
            }
        },
    )
}

And sync.Map becomes much faster when you increase the load, because of the memory being generated by immutable ds.

So when is lfmap more useful than sync.Map?

Also can you do an official benchmark and put it in the readme?

Snawoot commented 2 months ago

Hi, really like your stuff!

Hi! Thanks!

I did a benchmark for you map implementation

Great job! I really liked that framework you established! I changed your implementation a bit, added couple more things to bench and my results are:

goos: linux
goarch: amd64
pkg: github.com/Snawoot/lfmap
cpu: Intel(R) N100
BenchmarkLFMapSet-4                   199852         11756 ns/op
BenchmarkSyncMapSet-4                 864440          2424 ns/op
BenchmarkLFMapGet-4                  3098422           453.6 ns/op
BenchmarkSyncMapGet-4                5072394           216.5 ns/op
BenchmarkLFMapRange1000000-4               7     160304557 ns/op
BenchmarkSyncMapRange1000000-4             7     162762628 ns/op
PASS
ok      github.com/Snawoot/lfmap    33.638s

And sync.Map becomes much faster when you increase the load, because of the memory being generated by immutable ds.

So when is lfmap more useful than sync.Map?

So far lfmap is 2-6 times slower than sync.Map, mostly because of underlying immutable ds performance.

But performance aside, LFMap provides:

Also can you do an official benchmark and put it in the readme?

Your benchmark is now official one. The code with my changes is in master branch now.