Go Loador在sync.Map中存储,每次都不创建新结构

Go Loador在sync.Map中存储,每次都不创建新结构,go,concurrency,Go,Concurrency,是否可以在每次不创建新结构的情况下将装载机存储到Go中?如果没有,有哪些替代方案 这里的用例是,如果我使用sync.Map作为缓存,其中缓存未命中很少(但可能),并且对于要添加到映射中的缓存未命中,我需要在每次调用LoadOrStore时初始化结构,而不是在需要时创建结构。我担心这会伤害GC,初始化数十万个不需要的结构 在Java中,可以使用 Map类似于Go-Map[interface{}]interface{},但对于 由多个goroutine并发使用,无需额外锁定或 协调。加载、存储和

是否可以在每次不创建新结构的情况下将装载机存储到Go中?如果没有,有哪些替代方案

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

在Java中,可以使用

Map类似于Go-Map[interface{}]interface{},但对于 由多个goroutine并发使用,无需额外锁定或 协调。加载、存储和删除以摊销常量运行 时间

地图类型是专用的。大多数代码应该使用普通的Go映射 相反,使用单独的锁定或协调,以实现更好的类型安全性 并且更容易在地图上维护其他不变量 内容

映射类型针对两种常见用例进行了优化:(1)当 因为一个给定的密钥只写了一次,但读了很多次,如 仅增长的缓存,或(2)当多个goroutine读取、写入、, 并覆盖不相交的键集的条目。在这两种情况下,, 与Go相比,使用Map可以显著减少锁争用 映射与单独的互斥体或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\u 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

            }
        }
    }
}
主程序包
进口(
“strconv”
“同步”
“测试”
)
func BenchmarkHit(b*testing.b){
对于N:=0;N
您可以尝试:

var m sync.Map
s, ok := m.Load("key")
if !ok {
    s, _ = m.LoadOrStore("key", "value")
}

fmt.Println(s)

然而,这一可能的重复并不能回答这个问题。如何在Go中计算FabSent?具体地说,只有在映射中缺少新值时才创建新值?这个示例首先破坏了使用sync.map的意义
var m sync.Map
s, ok := m.Load("key")
if !ok {
    s, _ = m.LoadOrStore("key", "value")
}

fmt.Println(s)