Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >go 并发安全map新宠:xsync

go 并发安全map新宠:xsync

作者头像
超级大猪
发布于 2024-06-12 01:39:43
发布于 2024-06-12 01:39:43
28405
代码可运行
举报
文章被收录于专栏:大猪的笔记大猪的笔记
运行总次数:5
代码可运行

在go中,官方实现了并发安全的sync.Map。它的出现有一定争议(性能勉强),但因为并发安全,在go中仍然广泛使用。

今天介绍的xsync系列( &quot;github.com/puzpuzpuz/xsync/v3&quot;),使用了新的算法,对原官方的实现有一定的性能提升,此外,<mark style="background: #ff6666">它提供了Size方法</mark>,补充了官方sync.Map的一大短板。

此外,它还提供了CounterMPMCQueue(bounded multi-producer multi-consumer concurrent queue)RBMutex等多种并发安全结构。功能十分强大。

Map性能测试

机器

cpu: Intel(R) Xeon(R) Platinum 8255C CPU @ 2.50GHz

结论

go官方

xsync map

写入(store)

617.0 ns/op 65 B/op 5 allocs/op

70.51 ns/op 44 B/op 3 allocs/op

读取(load)

20.67 ns/op 0 B/op 0 allocs/op

5.596 ns/op 0 B/op 0 allocs/op (100万kv)

删除(delete)

20.34 ns/op 0 B/op 0 allocs/op

28.16 ns/op 0 B/op 0 allocs/op (100万kv)

元素数(size)

不支持

3.888 ns/op 0 B/op 0 allocs/op (100万kv)

xsync.Map有极大优势,尤其是在Store场景下,是替换系统sync.Map的优质选项。

附录

Store:写入

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// import 	&quot;github.com/puzpuzpuz/xsync/v3&quot;

func BenchmarkGosyncStore(b *testing.B) {
    m := sync.Map{}

    b.ResetTimer()
    b.RunParallel(func(pb *testing.PB) {
        i := 0
        for pb.Next() {
            m.Store(fmt.Sprint(i), i)
            i += 1
        }
    })
}

func BenchmarkXsyncStore(b *testing.B) {
    m := xsync.NewMapOf[string, int]()

    b.ResetTimer()

    b.RunParallel(func(pb *testing.PB) {
        i := 0
        for pb.Next() {
            m.Store(fmt.Sprint(i), i)
            i += 1
        }
    })
}

Load:读取

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func BenchmarkGosyncLoad(b *testing.B) {
    m := sync.Map{}
    for i := 0; i &lt; 1000000; i++ {
        m.Store(i, i)
    }

    b.ResetTimer()
    b.RunParallel(func(pb *testing.PB) {
        key := 0
        for pb.Next() {
            m.Load(key)
            key += 1
            if key &gt; 1000000 {
                key = 0
            }
        }
    })
}

func BenchmarkXsyncLoad(b *testing.B) {
    m := xsync.NewMapOf[int, int]()
    for i := 0; i &lt; 1000000; i++ {
        m.Store(i, i)
    }

    b.ResetTimer()
    b.RunParallel(func(pb *testing.PB) {
        key := 0
        for pb.Next() {
            m.Load(key)
            key += 1
            if key &gt; 1000000 {
                key = 0
            }
        }
    })
}

Delete:删除

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func BenchmarkGosyncDelete(b *testing.B) {
    m := sync.Map{}
    for i := 0; i &lt; 1000000; i++ {
        m.Store(i, i)
    }

    b.ResetTimer()
    b.RunParallel(func(pb *testing.PB) {
        key := 0
        for pb.Next() {
            m.Delete(key)
            key += 1
            if key &gt; 1000000 {
                key = 0
            }
        }
    })
}

func BenchmarkXsyncDelete(b *testing.B) {
    m := xsync.NewMapOf[int, int]()
    for i := 0; i &lt; 1000000; i++ {
        m.Store(i, i)
    }

    b.ResetTimer()
    b.RunParallel(func(pb *testing.PB) {
        key := 0
        for pb.Next() {
            m.Delete(key)
            key += 1
            if key &gt; 1000000 {
                key = 0
            }
        }
    })
}

Size:元素数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
func BenchmarkXmapSize(b *testing.B) {
    m := xsync.NewMapOf[int, int]()
    for i := 0; i &lt; 1000000; i++ {
        m.Store(i, i)
    }

    b.ResetTimer()
    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            m.Size()
        }
    })
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
我是如何实现Go性能5倍提升的?
代码的稳健、可读和高效是每一位 coder 的共同追求,写出更高效的代码不仅让自己爽、让 reviewer 赏心悦目,更能对业务带来实际的正面影响。本文将从实践及源码层面对 Go 的高性能编程进行解析,带你进入 Go 的高性能世界。
腾讯云开发者
2024/01/04
2.6K0
我是如何实现Go性能5倍提升的?
go 并发安全map之concurrent-map
concurrent-map的readme中说,这是一个高性能的并发安全的map,一起看源码来解读下他是如何实现高性能的。
tabbyzhou
2021/12/05
6.4K1
PHP转Go速学手册
整理了一份简要的手册,帮助大家高效的上手Go语言,主要是通过对比PHP和Go的不同点来强化理解,内容主要分为以下四部分:
用户1093396
2021/07/28
2.6K0
Go通过19:单元测试,确保高质量代码的秘诀!
您诸位好啊,我是无尘,今天我们进入到Go语言单元测试阶段,讲讲Go如何进行单元测试。
微客鸟窝
2021/08/18
5960
Go通过19:单元测试,确保高质量代码的秘诀!
Go语言性能优化- For Range 性能研究
如果我们要遍历某个数组,Map集合,Slice切片等,Go语言(Golang)为我们提供了比较好用的For Range方式。range是一个关键字,表示范围,和for配合使用可以迭代数组,Map等集合。它的用法简洁,而且map、channel等也都是用for range的方式,所以在编码中我们使用for range进行循环迭代是最多的。对于这种最常使用的迭代,尤其是和for i=0;i<N;i++对比,性能怎么样?我们进行下示例分析,让我们对for range循环有个更深的理解,便于我们写出性能更高的程序。
飞雪无情
2018/11/07
1.5K0
Go 常见 Test
将_test.go和.go文件放在同一目录下,运行go test -v可以详细执行测试,运行go test -cover可以检查测试覆盖率。
timerring
2025/02/13
1210
如何设计并实现一个线程安全的 Map ?(下篇)
在上篇中,我们已经讨论过如何去实现一个 Map 了,并且也讨论了诸多优化点。在下篇中,我们将继续讨论如何实现一个线程安全的 Map。说到线程安全,需要从概念开始说起。
一缕殇流化隐半边冰霜
2018/08/30
2.2K0
如何设计并实现一个线程安全的 Map ?(下篇)
GO 语言处理并发的时候我们是选择sync还是channel
以前写 C 的时候,我们一般是都通过共享内存来通信,对于并发去操作某一块数据时,为了保证数据安全,控制线程间同步,我们们会去使用互斥锁,加锁解锁来进行处理
阿兵云原生
2023/10/24
2980
GO 语言处理并发的时候我们是选择sync还是channel
Go Reflect 性能
Go reflect包提供了运行时获取对象的类型和值的能力,它可以帮助我们实现代码的抽象和简化,实现动态的数据获取和方法调用, 提高开发效率和可读性, 也弥补Go在缺乏泛型的情况下对数据的统一处理能力。
李海彬
2019/03/07
1K0
Go Reflect 性能
Go语言sync.Map一探究竟
sync.Map 是 Go 语言标准库中 sync 包提供的一个线程安全的 map,特别适用于读多写少的场景。相比于使用互斥锁(如 sync.Mutex 或 sync.RWMutex)来保护普通的 map,sync.Map 提供了更高的并发级别,通过减少锁的使用来优化性能。
闫同学
2024/09/08
3570
我好像发现了一个Go的Bug?
最近在重构一个路由功能,由于路由比较复杂,需求变化也多,于是想通过责任链模式来重构,刚好这段时间也在 Sentinel-Go 中看到相关源码。
龟仙老人
2021/12/08
4830
动手实现一个localcache - 欣赏优秀的开源设计
本地缓存的简单实现可以使用map[string]interface{} + sync.RWMutex的组合,使用sync.RWMutex对读进行了优化,但是当并发量上来以后,还是变成了串行读,等待锁的goroutine就会block住。为了解决这个问题我们可以进行分桶,每个桶使用一把锁,减少竞争。分桶也可以理解为分片,每一个缓存对象都根据他的key做hash(key),然后在进行分片:hash(key)%N,N就是要分片的数量;理想情况下,每个请求都平均落在各自分片上,基本无锁竞争。
Golang梦工厂
2022/07/11
3840
动手实现一个localcache - 欣赏优秀的开源设计
【Go】优雅的读取http请求或响应的数据-续
之前发布 【Go】优雅的读取http请求或响应的数据 文章,网友 “wxe” 咨询:“优化前后的请求耗时变化有多大”,之前只分析了内存分配,这篇文章用单元测试的方式分析优化前后的耗时情况,本文源码。
thinkeridea
2019/11/04
1.6K0
Go语言字符串高效拼接(二)
在上一篇关于字符串拼接的文章 Go语言字符串高效拼接(一) 中,我们演示的多种字符串拼接的方式,并且使用一个例子来测试了他们的性能,通过对比发现,我们觉得性能高的Builder并未发挥出其应该的性能,反而+号拼接,甚至strings.Join方法的性能更优越,那么这到底是什么原因呢?今天我们开始解开他们神秘的面纱,解开谜底。
飞雪无情
2018/12/06
6660
Golang sync.Map 简介与用法
Golang 中的 map 在并发情况下,只读是线程安全的,并发读写线程不安全。为了解决这个问题,Golang 提供了语言层级的并发读写安全的 sync.Map。
恋喵大鲤鱼
2019/07/12
10.9K0
Golang高性能编程实践
一个例子,content-service 在压测的时候发现过一个问题: 旧逻辑为了简化编码,在进行协议转换前,会对某些字段做一个 DeepCopy,因为转换过程需要原始数据,但我们完全可以通过一些处理逻辑的调整,比如调整先后顺序等移除 DeepCopy。优化前后性能对比如下:
腾讯技术工程官方号
2023/09/15
8531
Golang高性能编程实践
go 自旋锁
CAS算法是一种有名的无锁算法, 在不使用锁的情况下实现多线程之间的变量同步,而且没有堵塞线程.
Johns
2022/07/12
1.1K0
Go语言实战笔记(二十二)| Go 基准测试
基准测试,是一种测试代码性能的方法,比如你有多种不同的方案,都可以解决问题,那么到底是那种方案性能更好呢?这时候基准测试就派上用场了。
飞雪无情
2018/08/28
4270
深入理解 go sync.Map - 基本原理
我们知道,go 里面提供了 map 这种类型让我们可以存储键值对数据,但是如果我们在并发的情况下使用 map 的话,就会发现它是不支持并发地进行读写的(会报错)。 在这种情况下,我们可以使用 sync.Mutex 来保证并发安全,但是这样会导致我们在读写的时候,都需要加锁,这样就会导致性能的下降。 除了使用互斥锁这种相对低效的方式,我们还可以使用 sync.Map 来保证并发安全,它在某些场景下有比使用 sync.Mutex 更高的性能。 本文就来探讨一下 sync.Map 中的一些大家比较感兴趣的问题,比如为什么有了 map 还要 sync.Map?它为什么快?sync.Map 的适用场景(注意:不是所有情况下都快。)等。
闻说社
2025/07/16
1280
深入理解 go sync.Map - 基本原理
map和sync.map基准测试
在基准测试中,在并发安全的情况下sync.Map会比我们常用的map+读写锁更加的快,快了五倍,这是得以于只读read设计,减低锁的粒度。但是利用读写锁的话,我们存储的不是一个简单数据类型,而是一个指针对象,那么用普通map+读写锁能很好地控制锁的粒度,达到更好的操作。
用户7962184
2020/11/20
1.1K0
相关推荐
我是如何实现Go性能5倍提升的?
更多 >
领券
一站式MCP教程库,解锁AI应用新玩法
涵盖代码开发、场景应用、自动测试全流程,助你从零构建专属AI助手
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验