请问避免使用锁来提高性能的方式有哪些?

2018-01-12 17:15:57 +08:00
 herozem

在合理避免不必要的锁之外,还有什么办法可以提高性能呢?

最近写了一个熔断器,但是因为统计数据,URL 匹配等地方都需要加锁来使用(因为要面临并发修改数据的情况)。所以性能大概是 Nginx 的 3/5 左右。

目前能想到的是缩小锁的粒度。但是预计性能提升不会太大。

请问还有什么好办法可以规避锁的使用吗?

求方法 or 资料,非常感谢!

2361 次点击
所在节点    问与答
12 条回复
paw
2018-01-12 18:46:14 +08:00
如果只是为了统计数据,简单的全局变量++的话,原子变量
如果涉及梗复杂的结构,比如 map<somekey, uint64_t>这种,要先查再++的,做成每线程变量指向每线程独立的 map 结构,在需要统计的时候用指针交换的方式来拿到每线程的 map 做统计再释放。
paw
2018-01-12 18:47:50 +08:00
///没写完接上面
这样代码层面就完全无锁了。
但是原子变量会锁总线的,要是这个也想避免,就都用每线程变量指向一个 struct 进行++;
paw
2018-01-12 18:50:17 +08:00
妈蛋。纠正上面名词不对 。 每线程变量 >> 线程局部变量(Thread Local Variable)
WuwuGin
2018-01-12 18:56:25 +08:00
统计数据需要锁很少见吧,除非你真的需要精确到原子级和具体数据,建议换个思路放弃锁。
secondwtq
2018-01-12 19:12:46 +08:00
Is Parallel Programming Hard? And If So, What can you do about it? 这书里面一开始就讲了 counting problem
cloudzhou
2018-01-12 19:14:07 +08:00
先说语言
paw
2018-01-12 20:12:06 +08:00
如果 LZ 是 nginx 插件形式开发的,忽略我 1-3 楼的回答,我简单的吧场景想象成了单进程多线程的。

能详细描述下你的开发场景吗????
herozem
2018-01-12 21:28:35 +08:00
@paw
@WuwuGin
@secondwtq
@cloudzhou
Go 语言,统计部分是指统计过去一段时间的响应码,用这份统计数据来决定新的请求是否需要熔断,所以需要确保准确。
cloudzhou
2018-01-12 23:36:32 +08:00
如果 https://golang.org/pkg/sync/atomic/ 还不能满足,那你要思考整个设计了
另一个方式,局部本地变量累加,统计的时候汇总计算
cloudzhou
2018-01-12 23:39:06 +08:00
@herozem 使用 pprof,不要臆想
herozem
2018-01-13 11:25:58 +08:00
@cloudzhou 有用 pprof 分析的,虽然 topN 最前面的是 runtime 里的例如 defer,我自己写的代码里比较靠前的就是锁的相关操作了。统计这块应该可以用 channel 改造
ryd994
2018-01-14 22:47:35 +08:00
线程内各自统计,定时汇总

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/422423

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX