pull-drain-gently
Version:
Like pull.drain, but respects CPU load
92 lines (86 loc) • 2.36 kB
JavaScript
var Pausable = require('pull-pause');
var usage = require('cpu-percentage');
// We need our own drain, should not import from pull-stream
function drain(op, done) {
var read, abort;
function sink(_read) {
read = _read;
if (abort) return sink.abort();
(function next() {
var loop = true;
var cbed = false;
while (loop) {
cbed = false;
read(null, (end, data) => {
cbed = true;
if ((end = end || abort)) {
loop = false;
if (done) done(end === true ? null : end);
else if (end && end !== true) throw end;
} else if ((op && false === op(data)) || abort) {
loop = false;
read(abort || true, done || (() => {}));
} else if (!loop) {
next();
}
});
if (!cbed) {
loop = false;
return;
}
}
})();
}
sink.abort = (err, cb) => {
if (typeof err === 'function') (cb = err), (err = true);
abort = err || true;
if (read) return read(abort, cb || (() => {}));
};
return sink;
}
module.exports = function drainGently(a, b, c) {
var opFirst = !a || typeof a === 'function';
var opts = opFirst ? {ceiling: 88, wait: 144, maxPause: Infinity} : a;
var op = opFirst ? a : b;
var opDone = opFirst ? b : c;
var ceiling = opts.ceiling;
var wait = opts.wait;
var maxPause = opts.maxPause;
var pausable = Pausable();
var start = (stats = usage());
var lastResume = Date.now()
var step = 2,
i = 0;
function checkpoint() {
stats = usage(start);
if (
stats.percent < ceiling || // "CPU is cold enough"
stats.time < 20 || // "we just now began draining"
Date.now() - lastResume > maxPause // "remained paused for too long"
) {
step = step << 1 || 1;
lastResume = Date.now()
pausable.resume();
} else {
step = step >> 1 || 1;
pausable.pause();
setTimeout(checkpoint, wait);
}
}
function opWrapper(x) {
var res;
if (op) res = op(x);
if (++i >= step) {
i = 0;
checkpoint();
}
return res;
}
// The below does `return pull(pausable, drain(opWrapper, opDone))`:
var _sink = drain(opWrapper, opDone);
function sink(read) {
_sink(pausable(read));
}
sink.abort = _sink.abort;
return sink;
};