-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
x/tools/go/types/objectpath: add Encoder type, to amortize Scope.Names #58668
Comments
Change https://go.dev/cl/470679 mentions this issue: |
Change https://go.dev/cl/470678 mentions this issue: |
This change adds a new encoder type with For method, that is functionally equivalent to the old For function but avoids the surprising cost of repeated calls to Scope.Names and canonicalize (now called namedMethods), both of which allocate and sorts a slice. The former canonicalize function was previously applied to interface types too, but this was costly and unnecessary as they are already sorted. The public API change will have to wait for proposal 58668 to be accepted and thus fix issue 51017; this change uses the linkname hack to expose the function to x/tools to fix a pressing bug in gopls. See golang/go#58668 Updates golang/go#51017 Change-Id: Id3e8726517d31371b9376b0e47e320f8b6c5e085 Reviewed-on: https://go-review.googlesource.com/c/tools/+/470679 TryBot-Result: Gopher Robot <gobot@golang.org> gopls-CI: kokoro <noreply+kokoro@google.com> Run-TryBot: Alan Donovan <adonovan@google.com> Reviewed-by: Robert Findley <rfindley@google.com>
To add additional context: we simply wouldn't be able to use the objectpath package in gopls without this optimization. Furthermore, I think |
This proposal has been added to the active column of the proposals project |
The API is
Are there any concerns about this API? |
Based on the discussion above, this proposal seems like a likely accept. |
Overall I am in favor of this. I have one minor concern I might as well voice.
It is possible that if objectpath has such a scheme like this in the future, it might be more ergonomic for |
No change in consensus, so accepted. 🎉 |
Yes, and that's the existing contract of the objectpath package. Think of it schematically as:
If you need some other data structure (Table in your example) to make sense of the Path then either the Path is incomplete, or the Table is just something that can be derived from the Package by an analogous Decoder interface. You're right that there may be more efficient encodings of sets of Paths, but that's not a compatible evolution of this API. |
This change adds a new Encoder type with For method, that is functionally equivalent to the old For method but avoids the surprising cost of repeated calls to Scope.Names, which allocates and sorts a slice. See golang/go#58668 Fixes golang/go#51017 Change-Id: I328e60c60f9bc312af253a0509aa029c41960d41 Reviewed-on: https://go-review.googlesource.com/c/tools/+/470678 gopls-CI: kokoro <noreply+kokoro@google.com> Reviewed-by: Tim King <taking@google.com> Run-TryBot: Alan Donovan <adonovan@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This was fixed by https://go.dev/cl/470678. |
Change https://go.dev/cl/496875 mentions this issue: |
Updates golang/go#58668 Fixes golang/go#60330 Change-Id: I06bf739e9278028cbafb174b93699fbdfe98882f Reviewed-on: https://go-review.googlesource.com/c/tools/+/496875 Run-TryBot: Alan Donovan <adonovan@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> Auto-Submit: Alan Donovan <adonovan@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
@adonovan Wouldn't |
There has been a memoized version of namedMethods since CL 470679. Of course you have to use an objectpath.Encoder, but it's an easy change. [Edit: ignore me, replying before coffee.] |
I question whether it's necessary to sort named-type methods at all. So long as the export/import process preserves whatever order was there in the original types.Named produced from syntax, it doesn't actually matter what order that is. Perhaps we could just delete the expectation of Id-ordered method lists and use "whatever order go/types gives us". We should probably add some normative text to the Named.Method doc comment ("arbitrary but deterministic order"), and to the export/import package ("preserves order"), but then we could just remove the sort method. I see Rob just filed an issue. |
@adonovan unfortunately the sorting was added in https://go.dev/cl/354433 to fix https://go.dev/issue/44195. At the time, we didn't understand the implications of the fix. We're going to have to do something else to avoid the sort. It is prohibitively expensive when doing modular analysis of certain repositories. |
Fortunately that change didn't promise anything in the API, so I think we can simply use whatever unspecified yet deterministic order the type checker produces (and the exporter and importer preserve) and delete the sort. |
@adonovan that CL description cites parse independence as one of the main goals. Probably this requires more investigation. |
The CL description talks about "parse order" as if it is something different from "what's in the source file". I don't know why we would need or want to be independent of that. The attached issue is about the fact that gcexportdata used to sort and thus lose the order, but it has since been fixed so that it now preserves order. If go/types promises that method order is deterministic, and gcexportdata promises that it preserves method order, then there's nothing more to do. |
The objectpath.For function calls Scope.Names, which allocates and sorts a slice of all package members. If
For
is called for every member of a package (or for every declaration within a package, which is much more), then it incurs an amount of allocation that is quadratic in the number of package members. Some packages (e.g. for CPU instructions sets) are very large, and objectpath loops become so slow they appear to be stuck.I propose we add a new Encoder type with a For method so that new(Encoder).For gives the old behavior, but re-using the encoder across multiple calls for objects in the same package amortizes the expensive steps like Scope.Names.
See https://go.dev/cl/470679 for the expedient workaround in gopls (merged).
See https://go.dev/cl/470678 for the change to the public API.
The text was updated successfully, but these errors were encountered: