-
Notifications
You must be signed in to change notification settings - Fork 18k
go/types: add context to go/types.Config for cancelation #34683
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
Comments
Seems like a reasonable proposal but I'd rather not How about just a function One could even make this function have simple API (signature) that could be used to report progress/and or tracing, if one were so inclined. |
If there are useful pieces of metadata or actions beyond cancelation that are worth exposing then your suggestion sounds great to me. Something like type Config {
...
Checkpoint func(*CheckerStatus)
}
type CheckerStatus struct {}
func (*CheckerStatus) Cancel() {}
... If we want the actual I defer to you on whether there is other useful stuff that could take advantage of the generic callback. If there isn't other stuff in particular, then another option is adding |
I'm proposing a simpler solution, more akin to:
The installed |
cc: @alandonovan for input |
Is this necessary? The unit of type checking (and thus cancellation of type checking, today) is the package, and all but the largest packages type-check very quickly, in less than a typical keypress interval when editing. I don't know the implementation of gopls, but does it type check the complete source each time, or does it destroy function bodies for functions in files other than those of interest? If it did that optimization, and implemented cancelation at package granularity (and perhaps de-bounced the input event stream?) I imagine it would be fast enough. |
@alandonovan Good question; I don't know. @muirrn ? Also, something that comes to mind: It may the import processing where the time goes since importing one package may require type-checking that package's imports and the package itself (though all those things should be cached). But definitively worthwhile looking into time spent in an importer. |
There are definitely plenty of optimizations that can still be made within |
The main problem is synchronous LSP commands like completion. Editors often issue a completion request after every keypress, and to minimize completion latency gopls begins to type check ASAP. Any debouncing would reduce responsiveness. |
Understood, but completion needs to type-check at most one function body, plus all the package-level declarations of a package. It should run in well under a millisecond. |
In addition to completion and other language features, With the current Our concern is mostly CPU and memory usage, rather than speed. I'm currently debugging a memory leak 🙃, so I don't have accurate metrics yet, but once that is fixed, I will provide some more concrete data as justification. |
By its nature, the results of completion are required with very low latency as they help the user choose what to type, but diagnostics don't make sense until the program is at least reasonably well formed. Issuing diagnostic requests on every keystroke seems likely to lead to cascades of errors, distracting UI updates, wasted CPU cycles, and drained batteries. I don't think it's a strong justification for this feature. |
After some offline discussion with @alandonovan, I think our best approach here would be to check the context inside of the calls to |
BTW, although the old go/loader historically did actual work in the import function, go/packages, for many good reasons, does the work of loading and type checking dependencies of package P before even beginning to type-check P, so the Import function is just a map lookup. But logically, yes, we could profitably break off a cancelled type-checking task after loading only some of the dependencies. |
Thanks everyone. Closing as "rejected". BTW I really like the idea of doing a minor type check with only the containing function and package decls for synchronous commands like completion. That would make completions snappy even on giant packages (assuming the package isn't one giant function...). |
Change https://golang.org/cl/217257 mentions this issue: |
This change adds a check inside of the types.ImporterFunc to see if the context has been cancelled. Updates golang/go#34683 Change-Id: I0f12da0f8158ecda0eec00150ed6ff772c2f89c3 Reviewed-on: https://go-review.googlesource.com/c/tools/+/217257 Run-TryBot: Rohan Challa <rohan@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
I propose we add a mechanism to go/types so type checking can be canceled. gopls re-type checks packages in response to user edits, which can easily come in faster than type checking takes to complete. Because type checking is not cancelable, gopls builds up defunct type checking goroutines that eat up CPU and memory.
The most obvious cancelation mechanism would be to add a
context.Context
field to thetypes.Config
struct. During type checking, the context would be checked intermittently for doneness./cc @stamblerre @griesemer
The text was updated successfully, but these errors were encountered: