Browse files

Use the timer list for setTimeout

  • Loading branch information...
1 parent 7994400 commit bc47353bbe1836e4415cb08f1b6619839bff4d82 @ry ry committed Oct 26, 2010
Showing with 81 additions and 25 deletions.
  1. +15 −0 benchmark/settimeout.js
  2. +66 −25 lib/timers.js
View
15 benchmark/settimeout.js
@@ -0,0 +1,15 @@
+console.log("wait...");
+var done = 0;
+var N = 5000000;
+var begin = new Date();
+for (var i = 0; i < N; i++) {
+ setTimeout(function () {
+ if (++done == N) {
+ var end = new Date();
+ console.log("smaller is better");
+ console.log("startup: %d", start - begin);
+ console.log("done: %d", end - start);
+ }
+ }, 1000);
+}
+var start = new Date();
View
91 lib/timers.js
@@ -1,7 +1,7 @@
var Timer = process.binding('timer').Timer;
var assert = process.assert;
-/*
+/*
* To enable debug statements for the timers do NODE_DEBUG=8 ./node script.js
*/
var debugLevel = parseInt(process.env.NODE_DEBUG, 16);
@@ -48,9 +48,8 @@ function remove (item) {
// remove a item from its list and place at the end.
function append (list, item) {
- remove(item);
item._idleNext = list._idleNext;
- item._idleNext._idlePrev = item;
+ list._idleNext._idlePrev = item;
item._idlePrev = list;
list._idleNext = item;
}
@@ -62,7 +61,7 @@ function insert (item, msecs) {
item._idleStart = new Date();
item._idleTimeout = msecs;
- if (!msecs) return;
+ if (msecs < 0) return;
var list;
@@ -90,23 +89,23 @@ function insert (item, msecs) {
return;
} else {
remove(first);
- assert(first != peek(list));
+ assert(first !== peek(list));
if (first._onTimeout) first._onTimeout();
}
}
debug(msecs + ' list empty');
- assert(list._idleNext == list); // list is empty
+ assert(list._idleNext === list); // list is empty
list.stop();
};
}
- if (list._idleNext == list) {
+ if (list._idleNext === list) {
// if empty (re)start the timer
list.again(msecs);
}
append(list, item);
- assert(list._idleNext != list); // list is not empty
+ assert(list._idleNext !== list); // list is not empty
}
@@ -141,7 +140,7 @@ exports.enroll = function (item, msecs) {
// it will reset its timeout.
exports.active = function (item) {
var msecs = item._idleTimeout;
- if (msecs) {
+ if (msecs >= 0) {
var list = lists[msecs];
if (item._idleNext == item) {
insert(item, msecs);
@@ -159,41 +158,83 @@ exports.active = function (item) {
};
+/*
+ * DOM-style timers
+ */
+exports.setTimeout = function (callback, after) {
+ var timer;
-// Timers
-function addTimerListener (callback) {
- var timer = this;
- // Special case the no param case to avoid the extra object creation.
+ if (after <= 0) {
+ // Use the slow case for after == 0
+ timer = new Timer();
+ timer.callback = callback;
+ } else {
+ timer = { _idleTimeout: after, _onTimeout: callback };
+ timer._idlePrev = timer;
+ timer._idleNext = timer;
+ }
+
+ /*
+ * Sometimes setTimeout is called with arguments, EG
+ *
+ * setTimeout(callback, 2000, "hello", "world")
+ *
+ * If that's the case we need to call the callback with
+ * those args. The overhead of an extra closure is not
+ * desired in the normal case.
+ */
if (arguments.length > 2) {
var args = Array.prototype.slice.call(arguments, 2);
- timer.callback = function () { callback.apply(timer, args); };
- } else {
- timer.callback = callback;
+ var c = function () {
+ callback.apply(timer, args);
+ };
+
+ if (timer instanceof Timer) {
+ timer.callback = c;
+ } else {
+ timer._onTimeout = c;
+ }
}
-}
+ if (timer instanceof Timer) {
+ timer.start(0, 0);
+ } else {
+ exports.active(timer);
+ }
-exports.setTimeout = function (callback, after) {
- var timer = new Timer();
- addTimerListener.apply(timer, arguments);
- timer.start(after, 0);
return timer;
};
+
+exports.clearTimeout = function (timer) {
+ timer.callback = timer._onTimeout = null;
+ exports.unenroll(timer);
+ if (timer instanceof Timer) timer.stop(); // for after === 0
+};
+
+
exports.setInterval = function (callback, repeat) {
var timer = new Timer();
- addTimerListener.apply(timer, arguments);
+
+ if (arguments.length > 2) {
+ var args = Array.prototype.slice.call(arguments, 2);
+ timer.callback = function () {
+ callback.apply(timer, args);
+ };
+ } else {
+ timer.callback = callback;
+ }
+
timer.start(repeat, repeat ? repeat : 1);
return timer;
};
-exports.clearTimeout = function (timer) {
+
+exports.clearInterval = function (timer) {
if (timer instanceof Timer) {
timer.callback = null;
timer.stop();
}
};
-
-exports.clearInterval = exports.clearTimeout;

0 comments on commit bc47353

Please sign in to comment.