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
excessive wakeups/cpu usage with mode=raw jobs with close_cb but not out_cb #10758
Comments
When 'close_cb' is set for job_start(), but out_cb or err_cb isn't, vim buffers data instead of dropping it (in case someone wanted to read and process it in close_cb), and additionally polls for new data every 10 milliseconds, causing excessive wakeups and CPU usage. Since we don't read the data anywhere outside of out_cb/err_cb, any LSP that prints an error to stderr triggers this and vim keeps spinning until :ALEStopAllLSPs. Fix this by always setting both callbacks, thus dropping any data we're not interested in. See vim/vim#10758 for an upstream report of the excessive polling. It's possible this is intentional, I dunno. Fixes: b42153e ("Fix dense-analysis#4098 - Clear LSP data when servers crash")
### Steps to reproduce
1. `:let job = job_start('sh -c "echo x; cat"', {"mode": "raw", "close_cb": {->0}})`
2. `strace -f -p <pid-of-vim>`
### Expected behaviour
I expected to see the same output as I see after `:let job = job_start('sh -c "echo x; cat"', {"mode": "raw", "close_cb": {->0}, "out_cb": {->0}})`, that is:
```
pselect6(11, [0 6 8 10], [], [0], NULL, NULL
```
but what I got instead was a _lot_ of
```
pselect6(14, [0 6 8 10], [], [0], {tv_sec=0, tv_nsec=10000000}, NULL) = 0 (Timeout)
```
I investigated this a bit in gdb and found it being caused by
https://github.com/vim/vim/blob/b74e04649168aec579183dfef70b8784d2afe993/src/ui.c#L370-L371
What is the point of this polling? Is it useful for raw channels? I
gitblamed it back to 8a8199e but
can't say I understand the motivation.
The idea here, if I remember correctly, is that if there is a partly
received message, then we should check again soon to see if the rest of
the message is now available.
Perhaps in your specific situation there is readahead but checking for
more will never read anything?
…--
hundred-and-one symptoms of being an internet addict:
115. You are late picking up your kid from school and try to explain
to the teacher you were stuck in Web traffic.
/// Bram Moolenaar -- ***@***.*** -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|
The specific situation is mode=raw and no callback, so "there is readahead" just means there's pending input that hasn't been read and will not be read because there's no callback to read it, and also there's no known format/structure of the input that would suggest it's a partial input or not. Still, my question was a bit more general: when there is a known format/structure (e.g. json), why does vim need to do frequent polling instead of just waiting for ( |
When 'close_cb' is set for job_start(), but out_cb or err_cb isn't, vim buffers data instead of dropping it (in case someone wanted to read and process it in close_cb), and additionally polls for new data every 10 milliseconds, causing excessive wakeups and CPU usage. Since we don't read the data anywhere outside of out_cb/err_cb, any LSP that prints an error to stderr triggers this and vim keeps spinning until :ALEStopAllLSPs. Fix this by always setting both callbacks, thus dropping any data we're not interested in. See vim/vim#10758 for an upstream report of the excessive polling. It's possible this is intentional, I dunno. Fixes: b42153e ("Fix #4098 - Clear LSP data when servers crash")
> The idea here, if I remember correctly, is that if there is a partly received message, then we should check again soon to see if the rest of the message is now available.
> Perhaps in your specific situation there is readahead but checking for more will never read anything?
The specific situation is mode=raw and no callback, so "there is
readahead" just means there's pending input that hasn't been read and
will not be read because there's no callback to read it, and also
there's no known format/structure of the input that would suggest it's
a partial input or not.
Vim doesn't know about that. Besides a callback there are other ways to
read the text. You could add a callback that discards the text, then
there won't be this unused typahead.
Still, my question was a bit more general: when there is a known
format/structure (e.g. json), why does vim need to do frequent polling
instead of just waiting for (`p`)`select` to tell it there's new
input?
It might be possible to just depend on select() waking up, but it's very
tricky. There are a lot of things going on.
…--
"The sun oozed over the horizon, shoved aside darkness, crept along the
greensward, and, with sickly fingers, pushed through the castle window,
revealing the pillaged princess, hand at throat, crown asunder, gaping
in frenzied horror at the sated, sodden amphibian lying beside her,
disbelieving the magnitude of the frog's deception, screaming madly,
"You lied!"
- Winner of the Bulwer-Lytton contest (San Jose State University),
wherein one writes only the first line of a bad novel
/// Bram Moolenaar -- ***@***.*** -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|
Sure, that's what I ended up doing, it just seemed weird having to do this, with the docs not saying something like "the input must be read or else!" :-) |
…#4259) When 'close_cb' is set for job_start(), but out_cb or err_cb isn't, vim buffers data instead of dropping it (in case someone wanted to read and process it in close_cb), and additionally polls for new data every 10 milliseconds, causing excessive wakeups and CPU usage. Since we don't read the data anywhere outside of out_cb/err_cb, any LSP that prints an error to stderr triggers this and vim keeps spinning until :ALEStopAllLSPs. Fix this by always setting both callbacks, thus dropping any data we're not interested in. See vim/vim#10758 for an upstream report of the excessive polling. It's possible this is intentional, I dunno. Fixes: b42153e ("Fix dense-analysis#4098 - Clear LSP data when servers crash")
Steps to reproduce
:let job = job_start('sh -c "echo x; cat"', {"mode": "raw", "close_cb": {->0}})
strace -f -p <pid-of-vim>
Expected behaviour
I expected to see the same output as I see after
:let job = job_start('sh -c "echo x; cat"', {"mode": "raw", "close_cb": {->0}, "out_cb": {->0}})
, that is:but what I got instead was a lot of
I investigated this a bit in gdb and found it being caused by
vim/src/ui.c
Lines 370 to 371 in b74e046
What is the point of this polling? Is it useful for raw channels? I gitblamed it back to 8a8199e but can't say I understand the motivation.
(This is a real issue in https://github.com/dense-analysis/ale introduced recently by an addition of
close_cb
to a job without anerr_cb
, but it'll need to be fixed there anyway because a) needs a fix for older vim versions and b) accumulating stderr in some unbounded buffer somewhere is bad)Version of Vim
9.0.0057
Environment
OS: Linux (Debian testing)
the rest is irrelevant I believe
Logs and stack traces
No response
The text was updated successfully, but these errors were encountered: