go `cmd/compile: 深度嵌套结构中的指数行为`

qfe3c7zg  于 4个月前  发布在  Go
关注(0)|答案(7)|浏览(45)

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

你期望看到什么?

快速编译。

qnyhuwrf

qnyhuwrf1#

https://go.dev/cl/561875提到了这个问题:cmd/compile: caching result of AlgType

xggvc2p6

xggvc2p62#

https://go.dev/cl/561936提到了这个问题:cmd/compile: caching result of AlgType, EqCanPanic and PtrDataSize

s6fujrry

s6fujrry4#

再仔细观察一下,指数行为出现在 cmd/compile/internal/types.AlgTypecmd/compile/internal/types.PtrDataSize 中。然而,在最顶端,还有两个额外的违规者,cmd/compile/internal/types2.(*comparer).identicalcmd/compile/internal/types2.(*Checker).validType0。这些在 Go 的早期版本(比 tip 更早)的测试用例配置文件中没有出现(不像前两个)。二分查找指向 https://go-review.googlesource.com/c/go/+/567976 @griesemer

b1uwtaje

b1uwtaje5#

https://go.dev/cl/571543提到了这个问题:cmd/compile: compute ptrBytes during CalcSize instead of on demand

sbdsn5lh

sbdsn5lh6#

https://go.dev/cl/571542提到了这个问题:cmd/compile: compute type eq/hash algorithm in CalcSize instead of on demand

cwxwcias

cwxwcias7#

我会再次研究validType问题。尽管之前的代码在这种情况下有所帮助,但它是错误的。

相关问题