[gogf/gf]性能问题

2024-06-25 771 views
9

被gf的路由注册、数据库record、自带很多常用的工具集等特点吸引过来,确实方便,花了几天时间打磨出一套快速开发平台,包括权限系统、代码生成的功能,目前也有几个系统在此平台运行。 由于系统涉及到高并发大流量的场景,我做了很多的压测,发现内存不断的增加,3种注册方式都测试过,函数注册、对象注册、控制器注册都试过,甚至函数注册逻辑只渲染一个简单的模板页面,最终结果都会导致内存不断增加,增加到2G之后我就没再做测试,等了数个小时之后,内存才降到200多M。 周末在家,我用gin实现了同样的功能,包括模板输出和json输出,在高并发的情况下,内存稳定在36M。 当然,gin用起来确实没有gf爽快,我希望作者给出内存不断增长的原因。

回答

6

@piaohao 你好,麻烦提供以下这些信息呢,我会高优先级检查你说的问题。

运行平台:例如linux
平台架构:例如amd64
框架版本:例如v1.5.0
Go版本:例如1.11.4
可复现问题的最小化代码:
压测方式及工具:例如使用ab压测工具,测试地址为,并发用户,执行时间

其中复现代码那块比较重要,请务必提供一个最小化的代码以便于问题定位。

5

@johngcn 我刚写了一个测试项目,代码链接:https://github.com/piaohao/gf-test

运行平台:centos7.5
平台架构:amd64
框架版本:v1.5.4
Go版本:1.11.5
可复现问题的最小化代码:https://github.com/piaohao/gf-test
压测方式及工具:wrk -t 200 -c 500 -d 20 --latency http://localhost:8888/test

刚才进行了3轮压测,系统内存cpu截图如下: gf

7

@piaohao 收到,我看看

1

@piaohao 你用于测试对比的gin代码能否发我一下,我在本机上试试

1

@piaohao 你好gin的代码不用发我了,我定位到原因了,一会我再整理下把原因发你。

8

@piaohao GF框架的模板引擎内置了Session变量,开发者在使用模板引擎的时候默认会初始化一个Session(即使没有使用到Session功能),默认存放时间为600秒。单个空的Session占用内存约为51byte,那么100万的请求量所占内存量约为48.64MB

在压测的条件下,可能会造成内存泄露的错觉,实际上该问题的原因在于模板引擎初始化了没有必要的Session对象,目前该问题已修复,会随着下一个小版本更新,预计今天内发布。

本次修改之后,内存使用率稳定在0.2%左右,在我的机器上(16GB)对应的内存为32MBimage

7

@piaohao 你好,感谢反馈,针对该问题的修复已发布,请更新最新v1.5.5代码再试试。若有问题欢迎随时与我联系。

1

@johngcn 好的,先别关闭这个issue,我今天再做下全面的压测,跟gin比较下,等我的反馈

5

@piaohao 好的

1

经过一上午的测试,发现内存增长的问题依然存在,基本上定位在这里:

s.SetLogHandler(func(r *ghttp.Request, err ...interface{}) {
    glog.Cat("access").Backtrace(false, 2).Println("请求进来了")
})

整个代码我就不贴出来了,就在https://github.com/piaohao/gf-test这个项目的基础上,加上上面的代码,然后就能复现问题

5

哎,你这改动太随意了,线上又出了session的问题,

func (s *Session) Get (key string) interface{}  {
    if len(s.id) > 0 || s.request.Cookie.Contains(s.server.GetSessionIdName()) {
        s.init()
        return s.data.Get(key)
    }
    return nil
}

s.server为nil,空指针............... 没办法,只能回退到1.5.4了

0

@piaohao 稍等我看看

7

@piaohao 非常抱歉,这个涉及到gfpool的一个原子操作的BUG,会在高并发下造成内存占用过高,目前已修复。另外,添加了对WebServerSessionCookie的单元测试用例,昨天改的着急未加单元测试就发了,抱歉。请更新到最新的v1.5.6再试试。

9

@johngcn 初步测下来,内存稳定在66M,还算可以,明天继续测试,结合业务场景测试,看看还有没有其他问题

7

经过一晚上的压测,也跟gin进行了比较: image 最上面的是gf线上项目,中间的是gf-test项目,最下面的是gin-test项目。 压测接口的逻辑基本一致,gf内存最高峰比gin高15m左右,gf最终下降到30m,gin下降到16m,而gf线上项目启动的时候内存大概为15-20m。 那么问题来了,gf的内存为什么降到30m就不再下降了,初步判断应该是框架层面某些内存无法释放,请作者找明原因。

9

@piaohao

GF的初始化内存是比较与其他Web框架要高一点点,为项目化开发提供了更完备的开发组件,默认集成。同时,GF是有一些缓存机制,不过绝大部分都会自动释放(map delete),以供Go引擎回收再利用,Go runtime引擎会在适当的时候释放不再使用的内存(这个过程通常比较漫长,往往数小时不等)。

如果压测不再进行(最好是不再有任何请求),过了数小时(建议为2小时以上),但是仍然有比较高的内存占用,我可以进一步排查一下,但是这个和业务逻使用到的模块和方法有一定关系。需要你提供一下你压测的线上项目接口中,使用到的第三方库列表(该接口中涉及到的所有第三方库,不包括标准库)。例如可以通过目录搜索"github.com/关键词来查找,如果不仅仅使用GF,那么需要把其他的第三方库也列出来,以供判断。

如果能直接提供该测试接口的源代码当然更好,我能根据涉及到的方法更准确地定位。