被gf的路由注册、数据库record、自带很多常用的工具集等特点吸引过来,确实方便,花了几天时间打磨出一套快速开发平台,包括权限系统、代码生成的功能,目前也有几个系统在此平台运行。 由于系统涉及到高并发大流量的场景,我做了很多的压测,发现内存不断的增加,3种注册方式都测试过,函数注册、对象注册、控制器注册都试过,甚至函数注册逻辑只渲染一个简单的模板页面,最终结果都会导致内存不断增加,增加到2G之后我就没再做测试,等了数个小时之后,内存才降到200多M。 周末在家,我用gin实现了同样的功能,包括模板输出和json输出,在高并发的情况下,内存稳定在36M。 当然,gin用起来确实没有gf爽快,我希望作者给出内存不断增长的原因。
[gogf/gf]性能问题
回答
@piaohao 你好,麻烦提供以下这些信息呢,我会高优先级检查你说的问题。
运行平台:例如linux
平台架构:例如amd64
框架版本:例如v1.5.0
Go版本:例如1.11.4
可复现问题的最小化代码:
压测方式及工具:例如使用ab压测工具,测试地址为,并发用户,执行时间
其中复现代码那块比较重要,请务必提供一个最小化的代码以便于问题定位。
@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截图如下:
@piaohao 收到,我看看
@piaohao 你用于测试对比的gin代码能否发我一下,我在本机上试试
@piaohao 你好gin的代码不用发我了,我定位到原因了,一会我再整理下把原因发你。
@piaohao
GF框架的模板引擎内置了Session
变量,开发者在使用模板引擎的时候默认会初始化一个Session
(即使没有使用到Session
功能),默认存放时间为600
秒。单个空的Session
占用内存约为51byte
,那么100万的请求量所占内存量约为48.64MB
。
在压测的条件下,可能会造成内存泄露的错觉,实际上该问题的原因在于模板引擎初始化了没有必要的Session
对象,目前该问题已修复,会随着下一个小版本更新,预计今天内发布。
本次修改之后,内存使用率稳定在0.2%左右,在我的机器上(16GB)对应的内存为32MB
。
@piaohao 你好,感谢反馈,针对该问题的修复已发布,请更新最新v1.5.5
代码再试试。若有问题欢迎随时与我联系。
@johngcn 好的,先别关闭这个issue,我今天再做下全面的压测,跟gin比较下,等我的反馈
@piaohao 好的
经过一上午的测试,发现内存增长的问题依然存在,基本上定位在这里:
s.SetLogHandler(func(r *ghttp.Request, err ...interface{}) {
glog.Cat("access").Backtrace(false, 2).Println("请求进来了")
})
整个代码我就不贴出来了,就在https://github.com/piaohao/gf-test这个项目的基础上,加上上面的代码,然后就能复现问题
哎,你这改动太随意了,线上又出了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了
@piaohao 稍等我看看
@piaohao 非常抱歉,这个涉及到gfpool
的一个原子操作的BUG,会在高并发下造成内存占用过高,目前已修复。另外,添加了对WebServer
的Session
及Cookie
的单元测试用例,昨天改的着急未加单元测试就发了,抱歉。请更新到最新的v1.5.6
再试试。
@johngcn 初步测下来,内存稳定在66M,还算可以,明天继续测试,结合业务场景测试,看看还有没有其他问题
经过一晚上的压测,也跟gin进行了比较: 最上面的是gf线上项目,中间的是gf-test项目,最下面的是gin-test项目。 压测接口的逻辑基本一致,gf内存最高峰比gin高15m左右,gf最终下降到30m,gin下降到16m,而gf线上项目启动的时候内存大概为15-20m。 那么问题来了,gf的内存为什么降到30m就不再下降了,初步判断应该是框架层面某些内存无法释放,请作者找明原因。
@piaohao
GF
的初始化内存是比较与其他Web框架要高一点点,为项目化开发提供了更完备的开发组件,默认集成。同时,GF
是有一些缓存机制,不过绝大部分都会自动释放(map delete
),以供Go
引擎回收再利用,Go
runtime
引擎会在适当的时候释放不再使用的内存(这个过程通常比较漫长,往往数小时不等)。
如果压测不再进行(最好是不再有任何请求),过了数小时(建议为2小时以上),但是仍然有比较高的内存占用,我可以进一步排查一下,但是这个和业务逻使用到的模块和方法有一定关系。需要你提供一下你压测的线上项目接口中,使用到的第三方库列表(该接口中涉及到的所有第三方库,不包括标准库)。例如可以通过目录搜索"github.com/
关键词来查找,如果不仅仅使用GF
,那么需要把其他的第三方库也列出来,以供判断。
如果能直接提供该测试接口的源代码当然更好,我能根据涉及到的方法更准确地定位。