-
Notifications
You must be signed in to change notification settings - Fork 29.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
timers: Avoid linear scan in _unrefActive.
Before this change, _unrefActive would keep the unrefList sorted when adding a new timer. Because _unrefActive is called extremely frequently, this linear scan (O(n) at worse) would make _unrefActive show high in the list of contributors when profiling CPU usage. This commit changes _unrefActive so that it doesn't try to keep the unrefList sorted. The insertion thus happens in constant time. However, when a timer expires, unrefTimeout has to go through the whole unrefList because it's not ordered anymore. It is usually not large enough to have a significant impact on performance because: - Most of the time, the timers will be removed before unrefTimeout is called because their users (sockets mainly) cancel them when an I/O operation takes place. - If they're not, it means that some I/O took a long time to happen, and the initiator of subsequents I/O operations that would add more timers has to wait for them to complete. With this change, _unrefActive does not show as a significant contributor in CPU profiling reports anymore. Fixes: nodejs/node-v0.x-archive#8160 Signed-off-by: Timothy J Fontaine <[email protected]> Conflicts: lib/timers.js Fixes: nodejs/node-convergence-archive#23 Ref: #268 PR-URL: #2540 Reviewed-By: bnoordhuis - Ben Noordhuis <[email protected]>
- Loading branch information
1 parent
2308a27
commit 7a8c3e0
Showing
2 changed files
with
123 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
'use strict'; | ||
|
||
/* | ||
* This test is aimed at making sure that unref timers queued with | ||
* timers._unrefActive work correctly. | ||
* | ||
* Basically, it queues one timer in the unref queue, and then queues | ||
* it again each time its timeout callback is fired until the callback | ||
* has been called ten times. | ||
* | ||
* At that point, it unenrolls the unref timer so that its timeout callback | ||
* is not fired ever again. | ||
* | ||
* Finally, a ref timeout is used with a delay large enough to make sure that | ||
* all 10 timeouts had the time to expire. | ||
*/ | ||
|
||
const common = require('../common'); | ||
const timers = require('timers'); | ||
const assert = require('assert'); | ||
|
||
var someObject = {}; | ||
var nbTimeouts = 0; | ||
|
||
/* | ||
* libuv 0.10.x uses GetTickCount on Windows to implement timers, which uses | ||
* system's timers whose resolution is between 10 and 16ms. See | ||
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms724408.aspx | ||
* for more information. That's the lowest resolution for timers across all | ||
* supported platforms. We're using it as the lowest common denominator, | ||
* and thus expect 5 timers to be able to fire in under 100 ms. | ||
*/ | ||
const N = 5; | ||
const TEST_DURATION = 100; | ||
|
||
timers.unenroll(someObject); | ||
timers.enroll(someObject, 1); | ||
|
||
someObject._onTimeout = function _onTimeout() { | ||
++nbTimeouts; | ||
|
||
if (nbTimeouts === N) timers.unenroll(someObject); | ||
|
||
timers._unrefActive(someObject); | ||
}; | ||
|
||
timers._unrefActive(someObject); | ||
|
||
setTimeout(function() { | ||
assert.equal(nbTimeouts, N); | ||
}, TEST_DURATION); |