我已经开始分析我的一些 Go1.2 代码,最上面的项目总是名为“etext”的东西。我四处搜索,但除了可能与 Go 例程中的调用深度有关之外,找不到太多关于它的信息。但是,我没有使用任何 Go 例程,并且“etext”仍然占用了总执行时间的 75% 或更多。
(pprof) top20
Total: 171 samples
128 74.9% 74.9% 128 74.9% etext
任何人都可以解释这是什么以及是否有任何方法可以减少影响?
我遇到了同样的问题,然后我发现了这个:pprof 在 go 1.2 中损坏了?. 为了验证它确实是 1.2 的错误,我编写了以下“hello world”程序:
package main
import (
"fmt"
"testing"
)
func BenchmarkPrintln( t *testing.B ){
TestPrintln( nil )
}
func TestPrintln( t *testing.T ){
for i := 0; i < 10000; i++ {
fmt.Println("hello " + " world!")
}
}
如您所见,它只调用 fmt.Println。
您可以使用“go test –c”编译它。使用“./test.test -test.bench 运行。-test.cpuprofile=test.prof” 用“go tool pprof test.test test.prof”查看结果</p>
(pprof) top10
Total: 36 samples
18 50.0% 50.0% 18 50.0% syscall.Syscall
8 22.2% 72.2% 8 22.2% etext
4 11.1% 83.3% 4 11.1% runtime.usleep
3 8.3% 91.7% 3 8.3% runtime.futex
1 2.8% 94.4% 1 2.8% MHeap_AllocLocked
1 2.8% 97.2% 1 2.8% fmt.(*fmt).padString
1 2.8% 100.0% 1 2.8% os.epipecheck
0 0.0% 100.0% 1 2.8% MCentral_Grow
0 0.0% 100.0% 33 91.7% System
0 0.0% 100.0% 3 8.3% _/home/xxiao/work/test.BenchmarkPrintln
上面的结果是使用 go 1.2.1 得到的,然后我使用 go 1.1.1 做了同样的事情,得到了以下结果:
(pprof) top10
Total: 10 samples
2 20.0% 20.0% 2 20.0% scanblock
1 10.0% 30.0% 1 10.0% fmt.(*pp).free
1 10.0% 40.0% 1 10.0% fmt.(*pp).printField
1 10.0% 50.0% 2 20.0% fmt.newPrinter
1 10.0% 60.0% 2 20.0% os.(*File).Write
1 10.0% 70.0% 1 10.0% runtime.MCache_Alloc
1 10.0% 80.0% 1 10.0% runtime.exitsyscall
1 10.0% 90.0% 1 10.0% sweepspan
1 10.0% 100.0% 1 10.0% sync.(*Mutex).Lock
0 0.0% 100.0% 6 60.0% _/home/xxiao/work/test.BenchmarkPrintln
可以看到1.2.1的结果没有多大意义。Syscall 和 etext 占用大部分时间。1.1.1 结果看起来是对的。
所以我确信它确实是一个 1.2.1 的错误。我在实际项目中切换到使用 go 1.1.1,现在我对分析结果感到满意。
我认为 Mathias Urlichs 在您的 cgo 代码中缺少调试符号是正确的。值得注意的是,一些标准的 pkg,如 net 和 syscall 使用了 cgo。
如果您向下滚动到该文档的底部到名为“警告”的部分,您会看到第三个项目符号说...
如果程序链接在一个没有使用足够符号信息编译的库中,则与该库关联的所有样本可能会被计入该库之前在程序中找到的最后一个符号。这将人为地增加该符号的计数。
我不是 100% 肯定这是正在发生的事情,但我敢打赌这就是 etext 看起来如此忙碌的原因(换句话说,etext 是各种函数的集合,没有足够的信息供 pprof 正确分析。 )。