记录windows系统下go-torch报错问题
1. 错误信息
安装go-torch后,执行指令报“Failed: could not parse raw pprof output: strconv.ParseInt: parsing "os.(File).Write": invalid syntax”或者其他类似的 could not parse raw pprof output错误
2. 错误原因
先直接说原因哈,着急的同学看到这就可以了:
go sdk 安装到C:\Program Files,文件夹名有空格导致!!!
go sdk 安装到C:\Program Files,文件夹名有空格导致!!!
go sdk 安装到C:\Program Files,文件夹名有空格导致!!!
3. 错误分析
-
下载go-torch源码
-
根据错误提示“Failed: could not parse raw pprof output”找到在源码的位置(main.go文件)
-
由此处可以看出是pprof.ParseRaw函数返回的错误
-
点到这个方法里面,在可能出问题的地方加上断点,一点一点调试(具体过程略)。最终分析到在pprof/parse文件的processLine方法中出现问题(如下图)
-
继续深入分析该方法,在pprof/parse文件的180行发现问题,继续深入发现问题根因
-
上面已经猜测了问题出现的原因,那么如何验证呢?
-
go-torch的原理其实是执行pprof的指令,解析抽样采集文件的信息,大家在执行go-torch指令时都可以看到这一行(如下图),我们可以手动执行“go tool pprof -raw -seconds 30 [source]”命令,或者修改go-torch代码,把pprof解析后的值打印出来(pprof/pprof文件)
-
根据打印出的值来看(有点多,仅贴部分),搜索关键词“os.(File).Write”发现在这里有出现,结合第5步出现的addLocation方法逻辑分析,因为这行数据中的地址信息多了“空格”,导致在按空格分割后,切片长度为4,导出走错了逻辑,到此为止问题已分析完毕
4. 错误修复
那么既然已经发现问题,那如何修复问题呢
第一种: go sdk换个文件夹装,前提是改文件全路径不允许出现空格
第二种:修改go-torch源代码,重新编包
// pprof/pprof文件修改
func runPProf(args ...string) ([]byte, error) {
allArgs := []string{"tool", "pprof", "-raw"}
allArgs = append(allArgs, args...)
var buf bytes.Buffer
torchlog.Printf("Run pprof command: go %v", strings.Join(allArgs, " "))
cmd := exec.Command("go", allArgs...)
cmd.Stderr = &buf
out, err := cmd.Output()
if err != nil {
return nil, fmt.Errorf("pprof error: %v\nSTDERR:\n%s", err, buf.Bytes())
}
// @HACK because 'go tool pprof' doesn't exit on errors with nonzero status codes.
// Ironically, this means that Go's own os/exec package does not detect its errors.
// See issue here https://github.com/golang/go/issues/11510
if len(out) == 0 {
return nil, fmt.Errorf("pprof error:\n%s", buf.Bytes())
}
fmt.Println(string(out))
// 解决c盘文件夹出现空格问题,将空格替换掉
tmp := bytes2string(out)
tmp = strings.ReplaceAll(tmp, "Program Files", "ProgramFiles")
out = string2bytes(tmp)
return out, nil
}
// 字符串和切片零拷贝
func string2bytes(s string) []byte {
stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&s))
bh := reflect.SliceHeader{
Data: stringHeader.Data,
Len: stringHeader.Len,
Cap: stringHeader.Len,
}
return *(*[]byte)(unsafe.Pointer(&bh))
}
func bytes2string(b []byte) string {
sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
sh := reflect.StringHeader{
Data: sliceHeader.Data,
Len: sliceHeader.Len,
}
return *(*string)(unsafe.Pointer(&sh))
}
5. 生成火焰图报错问题
错误信息:could not generate flame graph: fork/exec flamegraph.pl: %1 is not a valid Win32 application 出现该问题就是还没装flamegraph插件
flamegraph安装:
git clone https://github.com/brendangregg/FlameGraph.git
将当前路径添加到windows系统环境变量下
perl sdk安装:
推荐网盘下载:https://pan.baidu.com/s/107UTzX-9_vgFPTW93Ec3AA
安装教程随便搜都有,这里就不介绍了