-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/compile: PGO does not devirtualize methods in another package (log: "no function body") #60561
Comments
https://go.dev/cl/497175 is my WIP CL to address the limitation you quoted by explicitly looking for missing functions in export data. Could you try cherry-picking that CL and see if it makes a difference? Note that you need to pass |
At first glance, I agree with your assessment. https://go.dev/cl/497175 should address the "missing IR" case, but the "no function body" case is surprising to me. Thanks for the detailed bug report. |
Brief comment for now, but will hopefully circle back tonight to try that CL. I suspect the "no function body" is causing it to fail unnecessarily, including it if encounters that error, it has already successfully gotten past the for _, e := range callerNode.OutEdges {
// ...
if e.Dst.AST == nil { I had a very simple test fix that seemed to work (in exactly one test 😅):
I can send that as a proof-of-concept CL, but maybe not needed if CL 497175 is the real fix. |
Change https://go.dev/cl/500155 mentions this issue: |
Hi @prattmic, if I try your CL 497175 (ps 1, fa555c12) on my original uncommented example:
I still get the
I also sent CL 500155, which was a quick exploratory hack. That does seem to successfully allow devirtualization:
Is your CL 497175 something that might be merged for 1.21, or is that more likely 1.22 at this point? If a more targeted fix is in order for 1.21, I'd be interested in trying to mature my CL 500155 into a real fix and add tests. (It is likely possible to do better than a string compare 😅). That said, I'd also of course understand if you'd prefer to address this yourself via CL 497175 or another CL. Thanks, and the PGO devirtualization work seems very promising! |
If I understand correctly, for imported inlineable functions, its |
Change https://go.dev/cl/500395 mentions this issue: |
Hi @cherrymui, thanks for the feedback! I updated my CL 500155 to use |
@cherrymui Great find, thanks. I'm not sure how I missed this before.
No, it will go in 1.22, it is too big for the freeze. |
Hi @cherrymui, FWIW, I'm also working on a update to tests for CL 500155 and I think I'm close to having that working. |
For reference, when building cmd/compile with PGO I see: At tip: 35 interface calls devirtualized (12.02% of interface call weight) So this is a nice boost in ability to devirtualize, but probably doesn't impact performance much (at least for cmd/compile). I'll run a full sweet run once we merge one of these fix CLs. |
Results from my benchmarking run:
It is hard to notice in the full list, but this fix did have quite a large impact on a few of these benchmarks:
|
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Feature only present in tip.
What did you do?
When experimenting with the new PGO-driven indirect call specialization from #59959, I did not see devirtualization happening on methods in another package, even when those methods are directly referenced in the current package.
CL 492436 notes that there are limitations in the first version of this, including:
However, I do not see devirtualization even after attempting to take that into account, though I might be holding it wrong.
I created a simplified example (playground link), which includes this main.go:
I then create a cpu profile:
And use that cpu profile with pgo:
The log shows
should not PGO devirtualize (*Speaker1).Speak: no function body
:If I comment out the only explicit uses of Speaker1.Speak and Speaker2.Speak in package main:
I then get a different log message saying
missing IR
for (*Speaker1).Speak:I suspect this second message of
missing IR
might be expected given the limitations listed in the CL because commenting out those lines means there are no explicit references to the Speak callees in package main, but I'm not sure that the first message ofno function body
is expected when those lines are not commented out.The
no function body
reason seems to be coming frominline.InlineImpossible(fn)
:Finally, regular inlining does appear to work on those methods (here using the original main.go, without having commented anything out):
What did you expect to see?
PGO-based devirtualization on methods in another package when those methods are directly referenced in the current package.
What did you see instead?
No devirtualization, with the log messages above.
Sorry in advance if this is just not supported yet, or if I've made a mistake.
CC @prattmic
The text was updated successfully, but these errors were encountered: