golang程序性能分析 红太狼 2022-05-26 01:24 215阅读 0赞 最近在使用GraphQL编写golang程序,但GraphQL框架在golang上的实践比较少,很多性能上的资料也不够全面。考虑到线上抗压的问题,笔者决定对自己开发的服务模块进行性能压测,评估下服务的整体性能。测试的工具链使用Vegeta+PPof+go-torch,PProf、go-torch上一篇文章[Golang工具链][Golang] 已经总结过不再赘述,vegeta会简单讲解下。 ## 工具-vegeta ## Vegeta是一个用Go语言编写的多功能的HTTP负载测试工具,提供命令行工具和开发包。安装见[vegeta][] 说明。 Usage: vegeta [global flags] <command> [command flags] global flags: -cpus int 使用CUP的数量 (默认 4 个) -profile string Enable profiling of [cpu, heap] -version 打印版本并退出 attack command: -body string 请求的主体文件 -cert string TLS客户PEM编码的证书文件 -connections int 没个目标主机最大打开闲置链接数 (默认 10000) -duration duration 持续攻击时间 [0 = forever] -header value 请求头 -insecure 忽略无效的服务器TLS证书 -keepalive 使用持久链接 (default true) -key string TLS客户端PEM编码的私钥文件 -laddr value 本地IP地址 (default 0.0.0.0) -lazy 延迟懒散的读取目标 -output string 输出文件 (default "stdout") -rate uint 每秒请求数 (default 50) -redirects int 遵循重定向的次数. -1 不会遵循重定向但会标记为成功 (默认 10) -root-certs value TLS根证书文件 (逗号分隔列表) -targets string 目标文件 (default "stdin") -timeout duration 请求超时时间 (default 30s) -workers uint 初始化进程数 (default 10) report command: -inputs string 输入文件 (comma separated) (default "stdin") -output string 输出文件 (default "stdout") -reporter string 表报字符格式 [text, json, plot, hist[buckets]] (default "text") text 文本格式 json json格式 plot 在 Dygraphs 上生成一个可以交互式的HTML5基础页面 hist 计算并打印一个基于文本的直方图 dump command: -dumper string Dumper [json, csv] (default "json") 指定转储格式 -inputs string Input files (comma separated) (default "stdin") 指定转储含有统计结果的输入文件,多个逗号分隔 -output string Output file (default "stdout") 指定把转储文件写入到输出文件 举例: echo "GET http://localhost/" | vegeta attack -duration=5s | tee results.bin | vegeta report vegeta attack -targets=targets.txt > results.bin vegeta report -inputs=results.bin -reporter=json > metrics.json cat results.bin | vegeta report -reporter=plot > plot.html cat results.bin | vegeta report -reporter="hist[0,100ms,200ms,300ms]" 注意 * \-targets 指定一行分隔文件中的攻击目标,格式如下: * 简单目标 GET http://goku:9090/path/to/dragon?item=balls GET http://user:password@goku:9090/path/to HEAD http://goku:9090/path/to/success * 自定义请求头的目标 GET http://user:password@goku:9090/path/to X-Account-ID: 8675309 DELETE http://goku:9090/path/to/remove Confirmation-Token: 90215 Authorization: Token DEADBEEF * 自定义请求的主体 POST http://goku:9090/things @/path/to/newthing.json PATCH http://goku:9090/thing/71988591 @/path/to/thing-71988591.json * 自定义请求头和请求主体 POST http://goku:9090/things X-Account-ID: 99 @/path/to/newthing.json * 进行负载测试时,不能因为Vegeta自身机器的性能瓶颈限制无法达到预期结果,例如打开的文件数、内存大小、CPU和网络带宽,分布式的使用Vegeta是非常好的解决方案。 * 为了确保打开文件描述和进程限制设置得高一些,可以在机器上使用`ulimit`命令 * 可以使用`pdsh`分布式运维工具,对目标执行分布式攻击。 ## 程序性能分析过程 ## ### 使用vegeta工具压测http服务接口 ### #### 命令 #### * `echo "POST http://192.168.168.189:8181/graphql" | vegeta attack -body /tmp/rqst/rqst.txt -duration=10s -rate=400 > r.bin` * 对`http://192.168.168.189:8181/graphql`执行post请求,post的body放置在`/tmp/rqst/rqst.txt`目录下,对目标地址进行持续10s的攻击,每次发送400个请求, 将请求的结果统计到r.bin文件。 * rqst.txt的内容如下,此处对部署在远端GraphQL服务直接发送Post请求,请求的操作名称jobInfoList: { "query":"query jobInfoList( $projectId: String!){\n\tjobInfoList(projectId: $projectId) {\n algorithmInfo {\n algorithmId\n descInfo\n location\n name\n sourceFormat\n status\n targetFormat\n version\n }\n }\n}", "variables":{"projectId":"pr-testproject"}, "operationName":"jobInfoList" } #### 结果 #### * text格式 /home# vegeta report -inputs=r.bin -reporter=text //查看text格式分析数据,默认为该格式,可不写 Requests [total, rate] 4000, 400.10 Duration [total, attack, wait] 10.0081328s, 9.997499937s, 10.632863ms Latencies [mean, 50, 95, 99, max] 3.978566ms, 3.635816ms, 6.189994ms, 11.539779ms, 18.534089ms Bytes In [total, mean] 148000, 37.00 Bytes Out [total, mean] 1380000, 345.00 Success [ratio] 100.00% Status Codes [code:count] 200:4000 * json格式 /home# vegeta report -inputs=r.bin -reporter=json { "latencies:{"total":15914265193,"mean":3978566,"50th":3635816,"95th":6189994,"99th":11539779,"max":18534089}, "bytes_in":{"total":148000,"mean":37}, "bytes_out":{"total":1380000,"mean":345}, "earliest":"2018-04-20T15:31:11.400851579+08:00","latest":"2018-04-20T15:31:21.398351516+08:00","end":"2018-04-20T15:31:21.408984379+08:00", "duration":9997499937, "wait":10632863, "requests":4000, "rate":400.10002752751205, "success":1, "status_codes":{"200":4000}, "errors":null } ### 查看生成的pprof分析的可视化图片 ### pprof常用作cpu、内存分析,需要使用pprof的场景 * 定位内存泄露 * 程序效率瓶颈 * 查看程序的调用图 下面这张图是CPU profile,可以清楚看到程序运行时的调用状态,主要分析各个方法的耗时。下图有些部分是虚线,是**因为耗时比较少的节点没有在图上体现出来** ,但要把图连起来,有的地方就使用虚线了。 ![这里写图片描述][70] ### go-torch更直观的分析工具 ### 上面的图在调用链比较简单的情况下,会比较直观,但在如此复杂的调用链下,确实看着有点乱,使用Uber开源的火焰图绝对让你打开新世界的大门。 ##### 命令 ##### * 执行命令`go-torch -u http://192.168.168.189:8181 -t 10` * 执行命令后bash展示如下内容: INFO[14:16:19] Run pprof command: go tool pprof -raw -seconds 10 http://192.168.168.189:8181/debug/pprof/profile INFO[14:16:30] Writing svg to torch.svg #### 火焰图展示 #### * 下图为使用go-torch生成的火焰图,看起来比pprof分析的要更加直观一些。 ![这里写图片描述][70 1] 火焰图是具有互动性的: * 鼠标悬浮: 火焰的每一层都会标注函数名,鼠标悬浮时会显示完整的函数名、抽样抽中的次数、占据总抽样次数的百分比。 ![这里写图片描述][70 2] * 点击放大:在某一层点击,火焰图会水平放大,该层会占据所有宽度,显示详细信息。 ![这里写图片描述][70 3] * 搜索:按下Ctrl + F 会显示一个搜索框,可输入关键字或正则表达式,所有符合条件的函数名会高亮显示 ![这里写图片描述][70 4] #### 总结 #### 通过以上一系列分析,笔者定位到`GraphQL`的解析库对程序的性能造成了一定的影响,这边总结了几种解决方式: * 用grpc替代GraphQL * http的Client和Server之间使用长连接进行通信 * 使用http2代替http1.1 ## 参考资料 ## * [Go代码调优利器-火焰图][Go_-] * [Golang服务的性能调优与问题定位][Golang 1] [Golang]: https://blog.csdn.net/phantom_111/article/details/79981579 [vegeta]: https://github.com/tsenart/vegeta [70]: /images/20220526/2de378b8772f44bda0df698a0d3e0090.png [70 1]: /images/20220526/71911587293d476c9755e7c3e9a34aa3.png [70 2]: /images/20220526/c5b2272dabd6440ab49cc34c227a0f3e.png [70 3]: /images/20220526/91f30d5215704ecc8fa779b0d93434d2.png [70 4]: /images/20220526/5b13b5ecaf7c4708bc067a0a083013be.png [Go_-]: http://lihaoquan.me/2017/1/1/Profiling-and-Optimizing-Go-using-go-torch.html [Golang 1]: http://www.yourmoonlight.com/golang/2017/07/15/How-To-Profile-Golang-Programs
相关 Java程序性能优化策略分析及实践示例 在Java编程中,提升程序性能主要从以下几个方面进行策略分析和实践: 1. **代码优化**: - 简化逻辑:避免嵌套循环、冗余条件判断。 - 使用高效数据结构: 待我称王封你为后i/ 2024年09月11日 16:39/ 0 赞/ 18 阅读
相关 ABAP程序性能优化 程序效率优化的重点: 降低CPU负载 降低数据库负载(减少IO操作) 内存使用的优化 减低CPU负载: 1. 使用WHERE条件减少循环次数。 即推荐: 淩亂°似流年/ 2022年09月18日 14:48/ 0 赞/ 180 阅读
相关 Spark程序性能优化 性能优化分析 一个计算任务的执行主要依赖于CPU、内存、带宽 Spark是一个基于内存的计算引擎,所以对它来说,影响最大的可能就是内存,一般我们的任务遇到了性能瓶颈大 拼搏现实的明天。/ 2022年09月10日 09:27/ 0 赞/ 223 阅读
相关 如何使用strace+pstack利器分析程序性能 如何使用strace+pstack利器分析程序性能 引言 有时我们需要对程序进行优化、减少程序响应时间。除了一段段地对代码进行时间复杂度分析,我们还有更便捷的方法 骑猪看日落/ 2022年08月09日 00:45/ 0 赞/ 146 阅读
相关 vtune性能分析工具--找出程序性能瓶颈 1. 概述 VTune是Intel一个比较强大的性能分析软件。主要包括三个小工具: (1)Performance Analyzer:性能分析,找到软件性能比较热的部分,一般 红太狼/ 2022年07月30日 20:51/ 0 赞/ 823 阅读
相关 程序性能评价指标 前言 前段时间,在搞压力测试。有众多的专业名词,大家可以了解一下。 -------------------- 指标 uv(unique vistor): 旧城等待,/ 2022年05月27日 02:56/ 0 赞/ 221 阅读
相关 golang程序性能分析 最近在使用GraphQL编写golang程序,但GraphQL框架在golang上的实践比较少,很多性能上的资料也不够全面。考虑到线上抗压的问题,笔者决定对自己开发的服务模块进 红太狼/ 2022年05月26日 01:24/ 0 赞/ 216 阅读
相关 Go程序性能分析pprof 開啓分析,插入代碼 import ( "runtime/pprof" // 引用pprof package "os" 曾经终败给现在/ 2022年05月23日 09:55/ 0 赞/ 153 阅读
相关 程序性能提高 在用C++写出高效地程序之前,必须认识到C++本身绝对与你所遇到的任何性能上的问题无关。如果想写出一个高效的C++程序,你必须首先能写出一个高效的算法。在一 桃扇骨/ 2021年06月24日 15:57/ 0 赞/ 488 阅读
还没有评论,来说两句吧...