diff options
| author | Cherry Mui <cherryyz@google.com> | 2022-11-01 12:33:58 -0400 |
|---|---|---|
| committer | Cherry Mui <cherryyz@google.com> | 2022-11-03 16:00:30 +0000 |
| commit | b07e845e764806fa888cb4e99c8ace4625f0472f (patch) | |
| tree | 551c84bb280ba74ad025c8555a572b1576170f7e /src/cmd/compile/internal/inline/inl.go | |
| parent | 932330fdbf669e28748227148f3f633620a5a300 (diff) | |
| download | go-b07e845e764806fa888cb4e99c8ace4625f0472f.tar.xz | |
cmd/compile: use CDF to determine PGO inline threshold
Currently in PGO we use a percentage threshold to determine if a
callsite is hot. This CL uses a different method -- treating the
hottest callsites that make up cumulatively top X% of total edge
weights as hot (X=95 for now). This default might work better for
a wider range of profiles. (The absolute threshold can still be
changed by a flag.)
For #55022.
Change-Id: I7e3b6f0c3cf23f9a89dd5994c10075b498bf14ee
Reviewed-on: https://go-review.googlesource.com/c/go/+/447016
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src/cmd/compile/internal/inline/inl.go')
| -rw-r--r-- | src/cmd/compile/internal/inline/inl.go | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 98bfb4e382..3f7ad34af3 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -29,6 +29,7 @@ package inline import ( "fmt" "go/constant" + "sort" "strconv" "strings" @@ -69,7 +70,13 @@ var ( inlinedCallSites = make(map[pgo.CallSiteInfo]struct{}) // Threshold in percentage for hot callsite inlining. - inlineHotCallSiteThresholdPercent = float64(0.1) + inlineHotCallSiteThresholdPercent float64 + + // Threshold in CDF percentage for hot callsite inlining, + // that is, for a threshold of X the hottest callsites that + // make up the top X% of total edge weight will be + // considered hot for inlining candidates. + inlineCDFHotCallSiteThresholdPercent = float64(95) // Budget increased due to hotness. inlineHotMaxBudget int32 = 160 @@ -77,11 +84,12 @@ var ( // pgoInlinePrologue records the hot callsites from ir-graph. func pgoInlinePrologue(p *pgo.Profile) { - if s, err := strconv.ParseFloat(base.Debug.InlineHotCallSiteThreshold, 64); err == nil { - inlineHotCallSiteThresholdPercent = s - if base.Debug.PGOInline > 0 { - fmt.Printf("hot-callsite-thres=%v\n", inlineHotCallSiteThresholdPercent) - } + if s, err := strconv.ParseFloat(base.Debug.InlineHotCallSiteCDFThreshold, 64); err == nil { + inlineCDFHotCallSiteThresholdPercent = s + } + inlineHotCallSiteThresholdPercent = computeThresholdFromCDF(p) + if base.Debug.PGOInline > 0 { + fmt.Printf("hot-callsite-thres-from-CDF=%v\n", inlineHotCallSiteThresholdPercent) } if base.Debug.InlineHotBudget != 0 { @@ -113,6 +121,38 @@ func pgoInlinePrologue(p *pgo.Profile) { } } +func computeThresholdFromCDF(p *pgo.Profile) float64 { + nodes := make([]pgo.NodeMapKey, len(p.NodeMap)) + i := 0 + for n := range p.NodeMap { + nodes[i] = n + i++ + } + sort.Slice(nodes, func(i, j int) bool { + ni, nj := nodes[i], nodes[j] + if wi, wj := p.NodeMap[ni].EWeight, p.NodeMap[nj].EWeight; wi != wj { + return wi > wj // want larger weight first + } + // same weight, order by name/line number + if ni.CallerName != nj.CallerName { + return ni.CallerName < nj.CallerName + } + if ni.CalleeName != nj.CalleeName { + return ni.CalleeName < nj.CalleeName + } + return ni.CallSite < nj.CallSite + }) + cum := int64(0) + for _, n := range nodes { + w := p.NodeMap[n].EWeight + cum += w + if pgo.WeightInPercentage(cum, p.TotalEdgeWeight) > inlineCDFHotCallSiteThresholdPercent { + return pgo.WeightInPercentage(w, p.TotalEdgeWeight) + } + } + return 100 +} + // pgoInlineEpilogue updates IRGraph after inlining. func pgoInlineEpilogue(p *pgo.Profile) { if base.Debug.PGOInline > 0 { |
