美文网首页@IT·互联网
Golang对象复用静态代码检查工具

Golang对象复用静态代码检查工具

作者: BeckJiang | 来源:发表于2021-03-04 22:57 被阅读0次

    一、对象复用

    在高并发的场景下使用golang,优化GC都会无法回避的问题。搜索「golang 垃圾回收优化」出来的结果基本上都会提及对象复用的方式,在实践中也确实很多高性能的开源库大量使用对象复用来优化程序,比如fasthttp。

    简单的例子

    使用对象复用分为三个环节,1.初始化pool;2.获取对象;3.清空对象+归还对象。

    package main
    import (
        "fmt"
        "sync"
    )
    
    var pool *sync.Pool
    
    type Person struct {
        Name string
    }
    
    func (p *Person)Reset() {
      p.Name = ""
    }
    
    func initPool() {
        pool = &sync.Pool {
            New: func()interface{} {
                fmt.Println("Creating a new Person")
                return new(Person)
            },
        }
    }
    
    func main() {
        // 1. 初始化池
        initPool()
        // 2. 获取对象
        p := pool.Get().(*Person)
    
        p.Name = "first"
    
        // 3. 清空对象 + 归还对象
        p.Reset()
        pool.Put(p)
    
    }
    

    二、对象复用的坑

    在上面的例子中,如果我们把Reset函数注释了,那么放回池子里的Person对象的Name是不干净的,很有可能会影响下一个使用的地方。不过实际使用中忘记调用Reset方法的比较少,这是对象复用的基本意识,真正容易遗漏的是Reset方法中的实现。

    在项目实践中,某些结构体定义的字段会比较多,而项目又一直在迭代,结构体的字段会发生新增、修改或删除,如果新增了字段,但Reset方法漏了新增对应的Reset语句,那么程序就很可能会出现数据篡乱的问题,而且这种问题不是稳定必现的,如果未意识到是字段漏了重置的问题,定位起来让人很头疼。

    三、工具比人靠谱

    想要避免出现这种问题,完全依赖个人注意肯定是不靠谱的,一个项目可能有多个人维护,团队也可能会有新人,难以确保每个人都能顾及到所有的对象复用。于是我开发了一个静态代码检查的工具 structreset用于检查对象复用的结构体的Reset方法,是否包含所有结构体字段的重置。当然这里的方法名Reset是我这里定义的,也可以叫别的名字:free/release等等。

    代码仓库里的实现是:识别带有refcount字段的结构体,然后遍历其Reset方法体语句。这个可以根据项目需求进行修改。

    var refCountTypeName = map[string]uint8 {"refcount": 1}
    

    安装

    按照文档操作即可。

    git clone git@git.xxx.cn:beckjiang/structreset.git
    
    cd structreset
    
    ./install.sh
    

    使用

    检查项目testdata

    structresetx -d ./analysis/passes/structreset/testdata
    
    image.png

    相关文章

      网友评论

        本文标题:Golang对象复用静态代码检查工具

        本文链接:https://www.haomeiwen.com/subject/zcgkqltx.html