-
Notifications
You must be signed in to change notification settings - Fork 29.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
perf_hooks: precise mode for monitorEventLoopDelay #32018
Conversation
@nodejs/performance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, it would be good to check how much overhead this adds compared to the timer approach.
Should we mentions somewhere that the actual numbers returned change? Before this PR they were biased by the resolution (e.g. a 10 ms timer but no extra delay resulted in 10ms), now the bias is 0 (which is a good thing in my opinion). I notices that the result looks not that nice if nothing happens between enable and disable but I think this is not caused by this PR. Most likely use of uninitialized variable or similar:
|
@Flarna good point! This is indeed the case. Another important change of behavior to consider: the timer was adding the data to histogram even without any event loop activity. With my change the data is emitted only when event loop delay actually happens. I can see how timer might be useful for reporting since histogram only reports aggregates. Do we care about this behavior change? Is it desirable? |
I'd hate to say it because it makes the implementation more complicated but I actually think having both available would be awesome. I.e. If resolution is provided, use the timer, if not, use the new semantics. |
Nope, this is intentional. The min is the max value for the field so that comparison with the original value to find the new minimum always works. Likewise for the max being zero so that comparisons to find the new max always work. The NaN's are indications that no data has been collected yet. |
This is a very good proposal. I'll give it a try. |
Introduce precise mode of `monitorEventLoopDelay` by using `uv_check_t` and `uv_prepare_t` instead of `uv_timer_t`.
a3eb955
to
334af98
Compare
monitorEventLoopDelay
@jsanell it is done |
@jasnell I understand this from implementation point of view but not regarding presenting the result to the user. Users don't have to do such comparsions. Anyhow it's not related to this PR. |
doc/api/perf_hooks.md
Outdated
lifecycle of the libuv event loop. That is, a delay in the loop will cause a | ||
delay in the execution of the timer, and those delays are specifically what this | ||
API is intended to detect. Timer-based monitoring happens continuously and adds | ||
delay statistics to the histogram even during standby. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we give hints about pros/conts of the two variants? I don't think that it is obvious to someone who isn't that familiar with the inner working of the event loop.
Co-Authored-By: Anna Henningsen <github@addaleax.net>
Please note that even after the change to combine the two implementations the behavior has changed in case no argument is given - it is and was optional. Personally I see no advantage of the timer variant. At least on windows timers are quite imprecise in case event look is idle. And honestly speaking who cares about event loop delay for an idle nodejs process? Don't get me wrong here, I don't want to block this. Edit: I found that my above statement is wrong, it still defaults to the 10ms timerbased approach. To get to the new |
Just an FYI #31988 has landed |
if (prev_ == 0) { | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super minor nit... as of late we've been moving away from {
}
's for single line ifs.
if (prev_ == 0) { | |
return; | |
} | |
if (prev_ == 0) | |
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it part of official code style for Node.js? make lint
didn't catch this.
If there any way to persuade, I'd insist that we keep parens even though (as many of you certainly know and remember) I was a proponent of omitting them. That apple kernel bug that was fixed some time ago has convinced me that omitting parens is error prone. I don't have a link to the kernel fix anymore, but it looked like this:
if (something)
if (something_else)
do_something();
Forgetting to put an if
body would result it in compiler interpreting the code in likely undesirable way.
That being said, I don't insist on changing existing code. Still it'd be great to write new code differently!
if (delta <= 0) { | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit...
if (delta <= 0) { | |
return; | |
} | |
if (delta <= 0) | |
return; |
if (ret) { | ||
return; | ||
} | ||
if (exceeds_ < 0xFFFFFFFF) { | ||
exceeds_++; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit...
if (ret) { | |
return; | |
} | |
if (exceeds_ < 0xFFFFFFFF) { | |
exceeds_++; | |
} | |
if (ret) | |
return; | |
if (exceeds_ < 0xFFFFFFFF) | |
exceeds_++; | |
Hey. After seeing this I sped up a PR I'd been planning to collect idle time in the kernel's event provider. I've posted it here: libuv/libuv#2725 I think it'll be helpful to take a look before landing this. |
Co-Authored-By: Sam Roberts <vieuxtech@gmail.com>
Co-Authored-By: Sam Roberts <vieuxtech@gmail.com>
Would changing the default value constitute a major version change or can it be released as minor? @nodejs/releasers (<- not sure if it is the right group) |
This is embarrassing, but after a conversation with @trevnorris I have to close this PR. I forgot that even though |
Sorry again y'all... |
Doh!! That's right. Don't feel bad because I forgot that also ;) |
@jasnell funny, but I think I've found a solution. The idea is to measure the time between |
Sorry, but I had to open a new Pull Request: #32102 . GitHub won't let me reopen this one after the force push (what a surprise!) |
Hi, quite off-topic questions but 1.) Does |
It should be minimal. The monitor creates a libuv timer that triggers based on the
Again, very minimal. You can see the definition of the underlying Histogram here. The amount of data stored really depends on the number of histogram buckets used but even that will be negligible. The longer the histogram runs, the more fixed it's approximate memory use should become. The reset is more about giving more control over data collection than memory management.
That's going to depend on your workload. Because it is using a timer for execution, which allows the event loop to turn in between calls, setting a high resolution makes is more likely that you will miss relevant samples. What I would do is profile your application to figure out what your typical event loop blocking range is under load and determine a resolution that catches the minimum of that range and higher. |
Introduce precise mode of
monitorEventLoopDelay
by usinguv_check_t
and
uv_prepare_t
instead ofuv_timer_t
.Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesNOTE: Updated the title and description of the issue on 2020-02-29