gpt4 book ai didi

go - 在 sync.Map 中加载或存储而无需每次都创建新结构

转载 作者:IT王子 更新时间:2023-10-29 01:40:51 25 4
gpt4 key购买 nike

是否可以将 LoadOrStore 放入 Go 中 sync.Map而不是每次都创建一个新的结构?如果没有,有哪些替代方案可用?

这里的用例是,如果我将 sync.Map 用作缓存,其中缓存未命中的情况很少见(但可能),并且在缓存未命中时我想添加到 map 中,我每次调用 LoadOrStore 时都需要初始化结构,而不是只在需要时创建结构。我担心这会伤害 GC,初始化数十万个不需要的结构。

在 Java 中,这可以使用 computeIfAbsent 来完成.

最佳答案

Package sync

import "sync"

type Map

Map is like a Go map[interface{}]interface{} but is safe for concurrent use by multiple goroutines without additional locking or coordination. Loads, stores, and deletes run in amortized constant time.

The Map type is specialized. Most code should use a plain Go map instead, with separate locking or coordination, for better type safety and to make it easier to maintain other invariants along with the map content.

The Map type is optimized for two common use cases: (1) when the entry for a given key is only ever written once but read many times, as in caches that only grow, or (2) when multiple goroutines read, write, and overwrite entries for disjoint sets of keys. In these two cases, use of a Map may significantly reduce lock contention compared to a Go map paired with a separate Mutex or RWMutex.


解决这些问题的通常方法是构建一个使用模型,然后对其进行基准测试。

例如,由于“缓存未命中的情况很少见”,假设 Load 将在大部分时间工作,并且只在必要时使用 LoadOrStore(具有值分配和初始化)。

$ go test map_test.go -bench=. -benchmem
BenchmarkHit-4 2 898810447 ns/op 44536 B/op 1198 allocs/op
BenchmarkMiss-4 1 2958103053 ns/op 483957168 B/op 43713042 allocs/op
$

map_test.go:

package main

import (
"strconv"
"sync"
"testing"
)

func BenchmarkHit(b *testing.B) {
for N := 0; N < b.N; N++ {
var m sync.Map
for i := 0; i < 64*1024; i++ {
for k := 0; k < 256; k++ {

// Assume cache hit
v, ok := m.Load(k)
if !ok {
// allocate and initialize value
v = strconv.Itoa(k)
a, loaded := m.LoadOrStore(k, v)
if loaded {
v = a
}
}
_ = v

}
}
}
}

func BenchmarkMiss(b *testing.B) {
for N := 0; N < b.N; N++ {
var m sync.Map
for i := 0; i < 64*1024; i++ {
for k := 0; k < 256; k++ {

// Assume cache miss
// allocate and initialize value
var v interface{} = strconv.Itoa(k)
a, loaded := m.LoadOrStore(k, v)
if loaded {
v = a
}
_ = v

}
}
}
}

关于go - 在 sync.Map 中加载或存储而无需每次都创建新结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51885117/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com