Go版本
提示
在你的模块/工作区中,go env
的输出是什么?
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/khr/Library/Caches/go-build"
GOENV="/Users/khr/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/khr/gopath/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/khr/gopath"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/Users/khr/go1.20.6"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/Users/khr/go1.20.6/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.20.6"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/z9/dty110711l9cr9w3ktv1_2380000gn/T/go-build2801687852=/tmp/go-build -gno-record-gcc-switches -fno-common"
你做了什么?
test.go
:
package a
type S0 struct{ a, b S1 }
type S1 struct{ a, b S2 }
type S2 struct{ a, b S3 }
type S3 struct{ a, b S4 }
type S4 struct{ a, b S5 }
type S5 struct{ a, b S6 }
type S6 struct{ a, b S7 }
type S7 struct{ a, b S8 }
type S8 struct{ a, b S9 }
type S9 struct{ a, b S10 }
type S10 struct{ a, b S11 }
type S11 struct{ a, b S12 }
type S12 struct{ a, b S13 }
type S13 struct{ a, b S14 }
type S14 struct{ a, b S15 }
type S15 struct{ a, b S16 }
type S16 struct{ a, b S17 }
type S17 struct{ a, b S18 }
type S18 struct{ a, b S19 }
type S19 struct{ a, b S20 }
type S20 struct{ a, b S21 }
type S21 struct{ a, b S22 }
type S22 struct{ a, b S23 }
type S23 struct{ a, b int }
使用以下命令进行编译:
go tool compile -cpuprofile=foo.prof ~/gowork/test.go
编译时间出乎意料地长。pprof输出指向 cmd/compile/internal/types/alg.go:AlgType
作为罪魁祸首。它正在遍历指数级大小的对象以确定其算法类别。它应该以某种方式对计算进行缓存,以免呈指数增长。
向示例添加更多行,使其变得更慢。
在 #65495 的讨论中发现。
你看到了什么发生?
flat flat% sum% cum cum%
2330ms 28.14% 28.14% 7470ms 90.22% cmd/compile/internal/types.AlgType
2040ms 24.64% 52.78% 2070ms 25.00% cmd/compile/internal/types.(*Type).Fields
1010ms 12.20% 64.98% 3850ms 46.50% cmd/compile/internal/types.IsPaddedField
640ms 7.73% 72.71% 790ms 9.54% cmd/compile/internal/types.PtrDataSize
你期望看到什么?
快速编译。
7条答案
按热度按时间qnyhuwrf1#
https://go.dev/cl/561875提到了这个问题:
cmd/compile: caching result of AlgType
xggvc2p62#
https://go.dev/cl/561936提到了这个问题:
cmd/compile: caching result of AlgType, EqCanPanic and PtrDataSize
zpjtge223#
@mdempsky
s6fujrry4#
再仔细观察一下,指数行为出现在
cmd/compile/internal/types.AlgType
和cmd/compile/internal/types.PtrDataSize
中。然而,在最顶端,还有两个额外的违规者,cmd/compile/internal/types2.(*comparer).identical
和cmd/compile/internal/types2.(*Checker).validType0
。这些在 Go 的早期版本(比 tip 更早)的测试用例配置文件中没有出现(不像前两个)。二分查找指向 https://go-review.googlesource.com/c/go/+/567976 @griesemerb1uwtaje5#
https://go.dev/cl/571543提到了这个问题:
cmd/compile: compute ptrBytes during CalcSize instead of on demand
sbdsn5lh6#
https://go.dev/cl/571542提到了这个问题:
cmd/compile: compute type eq/hash algorithm in CalcSize instead of on demand
cwxwcias7#
我会再次研究validType问题。尽管之前的代码在这种情况下有所帮助,但它是错误的。