条件断点

背景

查看到delve这条issues,对于条件断点会导致程序变慢很多

package main

import (  
    "fmt"
    "time"
)

func main() {  
    sum := int64(0)
    start := time.Now()
    for value := int64(0); value < 10000; value++ {
        sum += value  // break, cond 1 value==-1
    }
    elapsed := time.Since(start)
    fmt.Printf("Sum: %d\nTook %s\n", sum, elapsed)
}

上面的循环次数为10000,花费时间约13s,而实际直接debug不下断点时间为21.184µs(有波动,但是都在100µs以下)

// 条件debug
dlv debug ~/workspace/method/main.go                                          
Type 'help' for list of commands.  
(dlv) b main.go:12
Breakpoint 1 set at 0x4b40f5 for main.main() /home/chainhelen/workspace/method/main.go:12  
(dlv) cond 1 value==-1
(dlv) c
Sum: 49995000  
Took 13.516143652s  
Process 14748 has exited with status 0  
(dlv) 

// 直接debug
dlv debug ~/workspace/method/main.go                                          
Type 'help' for list of commands.  
(dlv) c
Sum: 49995000  
Took 21.184µs  
Process 15584 has exited with status 0

也就是说中间差了一个毫秒的数量级,1000倍上下的差异

查找原因

dlv项目里面的cmd/dlv/main.go添加性能分析代码

import  _ "net/http/pprof"

// 注意下面代码需要放在 cmds.New(false).Execute() 前面  
    go func() {
        log.Println(http.ListenAndServe("localhost:6060", nil))
    }() 

然后安装make install

按照上面的调试方式,在花费时间较长时间点的时候,下载文件http://localhost:6060/debug/pprof/profile?seconds=30

下载地址

分析图

火焰图

因为是svg格式,可以右键另外标签页打开

其中耗时较大的都是在利用trace获取register,尤其是虚拟寄存器fp;于是尝试写死fp寄存器的代码,发现实际并没有用到,`debug`是正常运行的,而且时间确实大幅度下降(仍然很慢)