使用golang的pprof包对程序进行性能分析
程序经常出现OOM错误,然后关键字"go pprof"搜到文章<Go程序性能分析pprof>,该文章第二步说运行程序后会生成profile文件,但是编译运行后发现生成的profile文件大小一直为0,然后关键字"go pprof profile is empty"搜到文章<Golang pprof heap profile is empty>,该文章说在运行程序前添加环境变量GODEBUG="memprofilerate=1",但是好像并没有用处。
然后还是之前的关键字"go pprof"搜到文章<使用golang的pprof包对程序进行性能分析>,该文章指出"在代码中使用pprof了,实际运用中分三种情况",因为程序并非是运行一次就退出,而是作为一个服务,所以"需要开启一个goroutine来开启端口监听",然后参考文章<go内存泄露case>,注意第二步"(2)memory profile"的描述"使用--alloc_space可以显示所有分配的对象",当使用web命令时会报错"Cannot find dot, have you installed Graphviz?",然后关键字"centos Graphviz"搜到文章<Linux Centos7安装配置画图工具Graphviz>,参照该文章安装了Graphviz但是web命令依然会报错"xdg-open: no method available for opening '/tmp/pprof-964683453/pprof001.svg'",不知道为什么就只好把临时的svg文件拷贝到windows下用ie来看,不理解为什么后面curl -T来拷贝时说该文件不存在。
如果程序代码中没有`import _ "net/http/pprof"`,则执行"go tool pprof http://localhost:6060/debug/pprof/heap"会报错"server response: 404 Not Found"。关键字"inuse_space"搜到文章<golang 内存分析/动态追踪>。
关键字"go 内存泄露"搜到文章<go内存泄露case>,该文章第一部分为gc相关"(1)观察GC",但是对输出的解释好像不太对(可能跟平台有关),就关键字"GODEBUG='gctrace=1'"搜到文章<golang中开启gctrace>,这篇文章中讲了两个部分:"垃圾回收信息"和"系统内存回收信息",但是"GODEBUG gctrace =1 ./xxxx.exe"却报错"-bash: GODEBUG: command not found"。后来试了文章<go内存泄露case>中的方法是可以的,即"GODEBUG='gctrace=1' ./xxxx.exe"。
关键字"go 调用c++"搜到博客园文章<golang调用c++文件>,"编译cc(c++)文件为动态链接库so文件 gcc -fPIC -shared hello.c -o libhello.so"。如果在源文件中调用malloc,编译报警告"incompatible implicit declaration of built-in function ‘malloc’",网上搜了下说应该加入头文件即可,即"#include<stdlib.h> #include<string.h>"。看了csdn上的文章<全面总结: Golang 调用 C/C++,例子式教程>,在"导入动态库 .so 或 .dll 的形式"这一步中,main.go内存去链接libvideo.so库的时候是-lvideo而不是llibvideo。否则会报错找不到库。
想测试下go调用c/c++代码,如果c/c++代码中出现内存泄漏,go的程序用top观察其RES段是什么样子,然后就在c代码中调用malloc,编译运行go程序并没有什么特别的,后来在c代码中在malloc后面调用memset,然后再编译运行go程序发现RES段就很明显,然后c代码中sleep一段时间后,调用free函数去释放申请的内存,编译运行go程序并top观察其RES段就会有下降。 后来又参考了文章<golang的cgo支持调用C++的方法>,同样的如果c++代码中申请了内存而没有释放,top观察go程序进程的RES段会发现占用比较高,如果释放后则会下降。而且用go tool pprof -inuse_space并不包含c++中申请的内存。奇怪如果C++代码中定义了一个static int arr[1024];的变量然后memset初始化,则编译得到的动态库.so被go的代码调用,然后go build test.go时会报错"/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1 /usr/local/go/src/runtime/alg.go:290:(.text+0x1163): relocation truncated to fit: R_X86_64_PC32 against `runtime.cpuid_ecx' /usr/local/go/src/runtime/alg.go:301:(.text+0x1267): relocation truncated to fit: R_X86_64_PC32 against `runtime.hashkey'"。