V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
herozem
V2EX  ›  问与答

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

  •  
  •   herozem · 2018-01-12 17:15:57 +08:00 · 2364 次点击
    这是一个创建于 2541 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

    能详细描述下你的开发场景吗????
    herozem
        8
    herozem  
    OP
       2018-01-12 21:28:35 +08:00 via iPad
    @paw
    @WuwuGin
    @secondwtq
    @cloudzhou
    Go 语言,统计部分是指统计过去一段时间的响应码,用这份统计数据来决定新的请求是否需要熔断,所以需要确保准确。
    cloudzhou
        9
    cloudzhou  
       2018-01-12 23:36:32 +08:00
    如果 https://golang.org/pkg/sync/atomic/ 还不能满足,那你要思考整个设计了
    另一个方式,局部本地变量累加,统计的时候汇总计算
    cloudzhou
        10
    cloudzhou  
       2018-01-12 23:39:06 +08:00
    @herozem 使用 pprof,不要臆想
    herozem
        11
    herozem  
    OP
       2018-01-13 11:25:58 +08:00 via iPhone
    @cloudzhou 有用 pprof 分析的,虽然 topN 最前面的是 runtime 里的例如 defer,我自己写的代码里比较靠前的就是锁的相关操作了。统计这块应该可以用 channel 改造
    ryd994
        12
    ryd994  
       2018-01-14 22:47:35 +08:00 via Android
    线程内各自统计,定时汇总
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2712 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 12:12 · PVG 20:12 · LAX 04:12 · JFK 07:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.