Add yield to Console.nudge(), remove old exponential nudge which didn't look right

This commit is contained in:
Justin SB
2014-10-14 13:26:53 -07:00
parent e02c254eab
commit d1fdb06103
6 changed files with 76 additions and 94 deletions

View File

@@ -195,10 +195,6 @@ var getCurrentProgressTracker = function () {
return progress ? progress : rootProgress;
};
var nudge = function () {
getCurrentProgressTracker().nudge();
};
var addChildTracker = function (title) {
var options = {};
options.title = title;
@@ -586,6 +582,5 @@ _.extend(exports, {
reportProgress: reportProgress,
reportProgressDone: reportProgressDone,
getCurrentProgressTracker: getCurrentProgressTracker,
addChildTracker: addChildTracker,
nudge: nudge
addChildTracker: addChildTracker
});

View File

@@ -311,20 +311,13 @@ _.extend(LayeredCatalog.prototype, {
var self = this;
var uniload = require('./uniload.js');
var yielder = new utils.ThrottledYield();
var constraintSolverPackage = uniload.load({
packages: [ 'constraint-solver']
})['constraint-solver'];
self.resolver =
new constraintSolverPackage.ConstraintSolver.PackagesResolver(self, {
nudge: function () {
// This may be a singleton, but the resolver is in a package so it
// doesn't have access to it.
utils.Patience.nudge();
buildmessage.nudge();
yielder.yield();
Console.nudge(true);
}
});
},

View File

@@ -23,6 +23,7 @@ var buildmessage = require('./buildmessage.js');
// XXX: Are we happy with chalk (and its sub-dependencies)?
var chalk = require('chalk');
var cleanup = require('./cleanup.js');
var utils = require('./utils.js');
PROGRESS_DEBUG = !!process.env.METEOR_PROGRESS_DEBUG;
FORCE_PRETTY=undefined;
@@ -135,6 +136,35 @@ _.extend(ProgressDisplayStatus.prototype, {
}
});
//var spinner = ['-', '\\', '|', '/'];
//// I looked at some Unicode indeterminate progress indicators, such as:
////
//// spinner = "▁▃▄▅▆▇▆▅▄▃".split('');
//// spinner = "▉▊▋▌▍▎▏▎▍▌▋▊▉".split('');
//// spinner = "▏▎▍▌▋▊▉▊▋▌▍▎▏▁▃▄▅▆▇▆▅▄▃".split('');
//// spinner = "▉▊▋▌▍▎▏▎▍▌▋▊▉▇▆▅▄▃▁▃▄▅▆▇".split('');
//// spinner = "⠉⠒⠤⣀⠤⠒".split('');
////
//// but none of them really seemed like an improvement. I think
//// the case for using unicode would be stronger in a determinate
//// progress indicator.
////
//// There are also some four-frame options such as ◐◓◑◒ at
//// http://stackoverflow.com/a/2685827/157965
//// but all of the ones I tried look terrible in the terminal.
//if (! self.quiet) {
// var animationFrame = 0;
// var printUpdate = fiberHelpers.bindEnvironment(function () {
// //runLog.logTemporary("=> Starting MongoDB... " +
// // spinner[animationFrame]);
// buildmessage.nudge();
// animationFrame = (animationFrame + 1) % spinner.length;
// });
// printUpdate();
// var mongoProgressTimer = setInterval(printUpdate, 200);
//}
var ProgressDisplayBar = function (console) {
var self = this;
@@ -285,7 +315,6 @@ _.extend(StatusPoller.prototype, {
});
}
}
});
var Console = function (options) {
@@ -297,7 +326,9 @@ var Console = function (options) {
self._progressDisplay = new ProgressDisplayNone(self);
self._statusPoller = null;
self._lastStatusPoll = 0;
self._throttledYield = new utils.ThrottledYield();
self._throttledStatusPoll = new utils.Throttled(STATUS_INTERVAL_MS);
self.verbose = false;
@@ -382,18 +413,19 @@ _.extend(Console.prototype, {
self.verbose = verbose;
},
// XXX: Move docs from Patience.nudge()
// Like Patience.nudge(); this can be called during long lived operations
// where the timer may be starved off the CPU. It will execute the poll if
// it has been 'too long'
nudge: function () {
nudge: function (canYield) {
var self = this;
var now = Date.now();
if ((now - self._lastStatusPoll) < STATUS_INTERVAL_MS) {
return;
if (self._throttledStatusPoll.isAllowed()) {
if (self._statusPoller) {
self._statusPoller.statusPoll();
}
}
// XXX: TODO: Add canYield argument and yield?
if (self._statusPoller) {
self._statusPoller.statusPoll();
if (canYield === true) {
self._throttledYield.yield();
}
},

View File

@@ -68,30 +68,6 @@ _.extend(Progress.prototype, {
self.reportProgress(state);
},
// For when we don't have a clear idea how long something will take,
// (i.e. no end estimate), just call nudge occasionally. We'll build
// an exponential progress bar for the task.
nudge: function () {
var self = this;
var halfLife = 25;
var state = _.clone(self._selfState);
if (!self._exponentialCounter) {
self._exponentialCounter = 1;
// Arbitrary endpoint
state.end = 100;
} else {
self._exponentialCounter++;
}
var fractionLeft = Math.pow(0.5, self._exponentialCounter / halfLife);
state.current = state.end * (1 - fractionLeft);
self.reportProgress(state);
},
// Tries to determine which is the 'current' job in the tree
// This is very heuristical... we use some hints, like:
// don't descend into fork-join jobs; we know these execute concurrently,
@@ -192,7 +168,7 @@ _.extend(Progress.prototype, {
self._updateTotalState();
console.Console.nudge();
console.Console.nudge(false);
self._notifyState();
},

View File

@@ -143,40 +143,11 @@ _.extend(Runner.prototype, {
}
if (! self.stopped && self.mongoRunner) {
var spinner = ['-', '\\', '|', '/'];
// I looked at some Unicode indeterminate progress indicators, such as:
//
// spinner = "▁▃▄▅▆▇▆▅▄▃".split('');
// spinner = "▉▊▋▌▍▎▏▎▍▌▋▊▉".split('');
// spinner = "▏▎▍▌▋▊▉▊▋▌▍▎▏▁▃▄▅▆▇▆▅▄▃".split('');
// spinner = "▉▊▋▌▍▎▏▎▍▌▋▊▉▇▆▅▄▃▁▃▄▅▆▇".split('');
// spinner = "⠉⠒⠤⣀⠤⠒".split('');
//
// but none of them really seemed like an improvement. I think
// the case for using unicode would be stronger in a determinate
// progress indicator.
//
// There are also some four-frame options such as ◐◓◑◒ at
// http://stackoverflow.com/a/2685827/157965
// but all of the ones I tried look terrible in the terminal.
if (! self.quiet) {
var animationFrame = 0;
var printUpdate = fiberHelpers.bindEnvironment(function () {
//runLog.logTemporary("=> Starting MongoDB... " +
// spinner[animationFrame]);
buildmessage.nudge();
animationFrame = (animationFrame + 1) % spinner.length;
});
printUpdate();
var mongoProgressTimer = setInterval(printUpdate, 200);
}
buildmessage.enterJob({ title: 'Starting MongoDB' }, function () {
self.mongoRunner.start();
});
if (! self.quiet) {
clearInterval(mongoProgressTimer);
if (! self.stopped)
runLog.log("=> Started MongoDB.");
}

View File

@@ -576,6 +576,7 @@ exports.Patience = function (options) {
}
};
// XXX: Remove
var nextYield = null;
var YIELD_EVERY_MS = 150;
var ACTIVE_PATIENCES = {};
@@ -646,34 +647,48 @@ _.extend(exports.Patience.prototype, {
}
});
// This is a stripped down version of Patience, that just regulates the frequency of calling yield.
// It should behave similarly to calling yield on every iteration of a loop,
// except that it won't actually yield if there hasn't been a long enough time interval
//
// options:
// interval: minimum interval of time between yield calls
// (more frequent calls are simply dropped)
//
// XXX: Have Patience use ThrottledYield
exports.ThrottledYield = function (options) {
exports.Throttled = function (options) {
var self = this;
options = _.extend({ interval: 150 }, options || {});
self.interval = options.interval;
var now = +(new Date);
// The next yield time is interval from now.
self.nextYield = now + self.interval;
self.next = now;
};
_.extend(exports.Throttled.prototype, {
isAllowed: function () {
var self = this;
var now = +(new Date);
if (now < self.next) {
return false;
}
self.next = now + self.interval;
return true;
}
});
// ThrottledYield just regulates the frequency of calling yield.
// It should behave similarly to calling yield on every iteration of a loop,
// except that it won't actually yield if there hasn't been a long enough time interval
//
// options:
// interval: minimum interval of time between yield calls
// (more frequent calls are simply dropped)
exports.ThrottledYield = function (options) {
var self = this;
self._throttle = new exports.Throttled(options);
};
_.extend(exports.ThrottledYield.prototype, {
yield: function () {
var self = this;
var now = +(new Date);
if (now >= self.nextYield) {
self.nextYield = now + self.interval;
if (self._throttle.isAllowed()) {
utils.sleepMs(1);
}
}