golang使用map支持高并发的方法(1000万次操作14ms)

11-17 200阅读 0评论

?=语言原生的Map存在2个问题:

1)不是线程安全的;

2)数据量大时候需要尽量避免使用string等,GC压力很大;

有人使用泛型实现了相关的cocurent-map,(https://github.com/orcaman/concurrent-map)但是关于键值部分仍然默认使用了string,为了提高效率,这里对其做了一些修改,让键值也可以自定义类型:https://github.com/robinfoxnan/Go_concurrent_map

基本使用方法

	// Create a new map. 	m := cache.NewConcurrentMap[UInt64, string]()   	// sets item within map, seTS "bar" under key "foo" 	m.Set(199010212, "bar")   	// Retrieve item from map. 	bar, ok := m.Get(199010212) 	fmt.Println(bar, ok)   	// Removes item under key "foo" 	m.Remove(199010212)

为了实现计数器等,需要在加锁期间更新,需要使用回调函数

// 计数type BaseCounter Struct { 	Count uint64 	CountLast uint64 }   var MapOfAppuserCount ConcurrentMap[uint64, *AppUserCounter]   func InitMaps() { 	MapOfAppVistedCount = NewConcurrentMap[uint64, *BaseCounter]() }   // 没有值,则设置;如果有,则更新; 新增的部分通过新的值传递过来! func appAddCallBack(exist bool, valueInMap *BaseCounter, newValue *BaseCounter) *BaseCounter { 	if exist == false { 		return newValue 	} else { 		valueInMap.Count += newValue.Count 		return valueInMap 	} }   // 对应用计数器加i func AppAddBy(key uint64, i uint64) uint64 { 	c := BaseCounter{i, i} 	res := MapOfAppVistedCount.Upsert(key, &c, appAddCallBack) 	if res != nil { 		return res.Count 	} 	return 0 }

计数器的使用如下:

cache.InitMaps() cache.AppAddBy(i, 1)

性能:

1)单线程初始化1~1000w的计数器,2412 ms

2)分给100个协程,14ms

测试代码如下:

 func testSingle() { 	cache.InitMaps() 	timeUnixNano1 := time.Now().UnixMilli() 	// 100万次更新 	for i := uint64(0); i < 10000000; i++ { 		cache.AppAddBy(i, 1) 	} 	timeUnixNano2 := time.Now().UnixMilli() 	delta := timeUnixNano2 - timeUnixNano1 	fmt.Println("cost: ", delta, " ms")   	count := cache.AppAddBy(1, 1) 	fmt.Println(count) 	count = cache.AppAddBy(1, 2) 	fmt.Println(count) 	count = cache.AppAddBy(1, 3) 	fmt.Println(count) }   var N int = 10000000   func doInsert(n int, index int, g *sync.WaitGroup) { 	m := N / n 	start := index * m   	//fmt.Println("thread ", index, "from ", start) 	for i := uint64(start); i < uint64(m); i++ { 		cache.AppAddBy(i, 1) 	} 	if g != nil { 		g.Done() 	} }   func testMulti() { 	cache.InitMaps()   	group := sync.WaitGroup{} 	n := 100 	group.Add(n) 	timeUnixNano1 := time.Now().UnixMilli() 	for i := 0; i < n; i++ { 		GO doInsert(n, i, &group) 	} 	group.Wait() 	timeUnixNano2 := time.Now().UnixMilli() 	delta := timeUnixNano2 - timeUnixNano1 	fmt.Println("cost: ", delta, " ms")   } 

到此这篇关于golang让map支持高并发(1000万次操作14ms)的文章就介绍到这了,更多相关Golang map并发内容请搜索云初冀北以前的文章或继续浏览下面的相关文章希望大家以后多多支持云初冀北!

免责声明
本站提供的资源,都来自网络,版权争议与本站无关,所有内容及软件的文章仅限用于学习和研究目的。不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负,我们不保证内容的长久可用性,通过使用本站内容随之而来的风险与本站无关,您必须在下载后的24个小时之内,从您的电脑/手机中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。侵删请致信E-mail:goliszhou@gmail.com
$

发表评论

表情:
评论列表 (暂无评论,200人围观)

还没有评论,来说两句吧...