Comparing version 1.1.5 to 1.1.6
@@ -34,2 +34,67 @@ /* | ||
/* | ||
* Parameters for the EMA/low-pass filter that is used to limit pool shrinkage | ||
* under sustained load. The idea is to stop the pool from shrinking too | ||
* rapidly if the average load has been high recently. This stops us from | ||
* over-reacting to small transients in load and generally stablizes behavior. | ||
*/ | ||
/* Sample rate of the filter, in Hz. */ | ||
var LP_RATE = 5; | ||
/* One sampling interval. */ | ||
var LP_INT = Math.round(1000 / LP_RATE); | ||
/* The filter taps array. See below for parameters' meaning. */ | ||
var LP_TAPS = genTaps(128, -0.2); | ||
/* | ||
* Generates a set of EMA taps: count is the number of taps to generate, and | ||
* tc is the value of the time constant of decay. This should be negative | ||
* and fractional. The closer it gets to 0.0 (while remaining negative), the | ||
* lower its low-pass cutoff frequency will be and the sharper the filter | ||
* roll-off becomes. | ||
* | ||
* A tc of -0.2 at 5Hz creates an EMA filter with a pass band extending out | ||
* to about 0.25Hz (4-second period), -10dB point at 0.5Hz, -20dB point at | ||
* 2.5Hz. This means that the filter reacts most strongly to trends with | ||
* principal components of around 4 seconds period or more -- any faster | ||
* trends will be gradually suppressed, and for trends of 400ms or less, down | ||
* to about 1% of their original magnitude. | ||
*/ | ||
function genTaps(count, tc) { | ||
var taps = new Float64Array(count); | ||
var sum = 0.0; | ||
for (var i = 0; i < count; ++i) { | ||
taps[i] = Math.exp(tc * i); | ||
sum += taps[i]; | ||
} | ||
for (i = 0; i < count; ++i) { | ||
taps[i] /= sum; | ||
} | ||
return (taps); | ||
} | ||
/* A simple FIR filter with a circular buffer. */ | ||
function FIRFilter(taps) { | ||
this.f_taps = taps; | ||
this.f_buf = new Float64Array(taps.length); | ||
this.f_ptr = 0; | ||
} | ||
FIRFilter.prototype.put = function (v) { | ||
this.f_buf[this.f_ptr++] = v; | ||
/* Wrap around to zero if we go off the end. */ | ||
if (this.f_ptr === this.f_taps.length) | ||
this.f_ptr = 0; | ||
}; | ||
FIRFilter.prototype.get = function () { | ||
var i = this.f_ptr - 1; | ||
if (i < 0) | ||
i += this.f_taps.length; | ||
var acc = 0.0; | ||
for (var j = 0; j < this.f_taps.length; ++j) { | ||
acc += this.f_buf[i] * this.f_taps[j]; | ||
if (--i < 0) | ||
i += this.f_taps.length; | ||
} | ||
return (acc); | ||
}; | ||
/* | ||
* A ConnectionPool holds a pool of ConnectionFSMs that are kept up to date | ||
@@ -108,2 +173,3 @@ * based on the output of a Resolver. At any given time the pool may contain: | ||
this.p_startedResolver = false; | ||
this.p_lpf = new FIRFilter(LP_TAPS); | ||
@@ -150,2 +216,18 @@ this.p_idleq = new Queue(); | ||
this.p_lastRebalClamped = false; | ||
this.p_lpTimer = setInterval(function () { | ||
var conns = 0; | ||
Object.keys(self.p_connections).forEach(function (k) { | ||
conns += self.p_connections[k].length; | ||
}); | ||
var spares = self.p_idleq.length + self.p_initq.length; | ||
var busy = conns - spares; | ||
self.p_lpf.put(busy + self.p_spares); | ||
if (self.p_lastRebalClamped) | ||
self.rebalance(); | ||
}, LP_INT); | ||
this.p_lpTimer.unref(); | ||
FSM.call(this, 'starting'); | ||
@@ -350,2 +432,3 @@ } | ||
clearInterval(this.p_shuffleTimerInst); | ||
clearInterval(this.p_lpTimer); | ||
}; | ||
@@ -427,2 +510,11 @@ | ||
var target = busy + extras + this.p_spares; | ||
var min = Math.ceil(this.p_lpf.get()); | ||
if (target < min * 1.05) { | ||
target = min; | ||
this.p_lastRebalClamped = true; | ||
} else { | ||
this.p_lastRebalClamped = false; | ||
} | ||
if (target > this.p_max) | ||
@@ -607,2 +699,4 @@ target = this.p_max; | ||
this._incrCounter('claim'); | ||
if (this.isInState('stopping') || this.isInState('stopped')) { | ||
@@ -609,0 +703,0 @@ setImmediate(function () { |
{ | ||
"name": "cueball", | ||
"version": "1.1.5", | ||
"version": "1.1.6", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3632
151377
15