ソースを参照

RingBuffer<> is now templated with size, buffer is now static.

Adam Ierymenko 6 年 前
コミット
d530356055
6 ファイル変更95 行追加247 行削除
  1. 31 47
      node/Path.hpp
  2. 2 3
      node/Peer.cpp
  3. 2 6
      node/Peer.hpp
  4. 4 117
      node/Poly1305.cpp
  5. 52 70
      node/RingBuffer.hpp
  6. 4 4
      node/Utils.hpp

+ 31 - 47
node/Path.hpp

@@ -123,7 +123,8 @@ public:
 		_lastComputedThroughputDistCoeff(0.0),
 		_lastAllocation(0)
 	{
-		prepareBuffers();
+		memset(_ifname, 0, 16);
+		memset(_addrString, 0, sizeof(_addrString));
 	}
 
 	Path(const int64_t localSocket,const InetAddress &addr) :
@@ -155,22 +156,11 @@ public:
 		_lastComputedThroughputDistCoeff(0.0),
 		_lastAllocation(0)
 	{
-		prepareBuffers();
+		memset(_ifname, 0, 16);
+		memset(_addrString, 0, sizeof(_addrString));
 		_phy->getIfName((PhySocket *)((uintptr_t)_localSocket), _ifname, 16);
 	}
 
-	~Path()
-	{
-		delete _throughputSamples;
-		delete _latencySamples;
-		delete _packetValiditySamples;
-		delete _throughputDisturbanceSamples;
-		_throughputSamples = NULL;
-		_latencySamples = NULL;
-		_packetValiditySamples = NULL;
-		_throughputDisturbanceSamples = NULL;
-	}
-
 	/**
 	 * Called when a packet is received from this remote path, regardless of content
 	 *
@@ -216,7 +206,7 @@ public:
 		else {
 			_latency = l;
 		}
-		_latencySamples->push(l);
+		_latencySamples.push(l);
 	}
 
 	/**
@@ -345,7 +335,7 @@ public:
 				_inQoSRecords[packetId] = now;
 				_packetsReceivedSinceLastQoS++;
 			}
-			_packetValiditySamples->push(true);
+			_packetValiditySamples.push(true);
 		}
 	}
 
@@ -362,7 +352,7 @@ public:
 		int64_t timeSinceThroughputEstimate = (now - _lastThroughputEstimation);
 		if (timeSinceThroughputEstimate >= ZT_PATH_THROUGHPUT_MEASUREMENT_INTERVAL) {
 			uint64_t throughput = (float)(_bytesAckedSinceLastThroughputEstimation * 8) / ((float)timeSinceThroughputEstimate / (float)1000);
-			_throughputSamples->push(throughput);
+			_throughputSamples.push(throughput);
 			_maxLifetimeThroughput = throughput > _maxLifetimeThroughput ? throughput : _maxLifetimeThroughput;
 			_lastThroughputEstimation = now;
 			_bytesAckedSinceLastThroughputEstimation = 0;
@@ -564,7 +554,7 @@ public:
 	 * Record an invalid incoming packet. This packet failed MAC/compression/cipher checks and will now
 	 * contribute to a Packet Error Ratio (PER).
 	 */
-	inline void recordInvalidPacket() { _packetValiditySamples->push(false); }
+	inline void recordInvalidPacket() { _packetValiditySamples.push(false); }
 
 	/**
 	 * @return A pointer to a cached copy of the address string for this Path (For debugging only)
@@ -582,35 +572,43 @@ public:
 	 *
 	 * @param now Current time
 	 */
-	inline void processBackgroundPathMeasurements(int64_t now) {
+	inline void processBackgroundPathMeasurements(const int64_t now)
+	{
 		if (now - _lastPathQualityComputeTime > ZT_PATH_QUALITY_COMPUTE_INTERVAL) {
 			Mutex::Lock _l(_statistics_m);
 			_lastPathQualityComputeTime = now;
 			address().toString(_addrString);
-			_lastComputedMeanLatency = _latencySamples->mean();
-			_lastComputedPacketDelayVariance = _latencySamples->stddev(); // Similar to "jitter" (SEE: RFC 3393, RFC 4689)
-			_lastComputedMeanThroughput = (uint64_t)_throughputSamples->mean();
+			_lastComputedMeanLatency = _latencySamples.mean();
+			_lastComputedPacketDelayVariance = _latencySamples.stddev(); // Similar to "jitter" (SEE: RFC 3393, RFC 4689)
+			_lastComputedMeanThroughput = (uint64_t)_throughputSamples.mean();
+
 			// If no packet validity samples, assume PER==0
-			_lastComputedPacketErrorRatio = 1 - (_packetValiditySamples->count() ? _packetValiditySamples->mean() : 1);
+			_lastComputedPacketErrorRatio = 1 - (_packetValiditySamples.count() ? _packetValiditySamples.mean() : 1);
+
 			// Compute path stability
 			// Normalize measurements with wildly different ranges into a reasonable range
 			float normalized_pdv = Utils::normalize(_lastComputedPacketDelayVariance, 0, ZT_PATH_MAX_PDV, 0, 10);
 			float normalized_la = Utils::normalize(_lastComputedMeanLatency, 0, ZT_PATH_MAX_MEAN_LATENCY, 0, 10);
-			float throughput_cv = _throughputSamples->mean() > 0 ? _throughputSamples->stddev() / _throughputSamples->mean() : 1;
+			float throughput_cv = _throughputSamples.mean() > 0 ? _throughputSamples.stddev() / _throughputSamples.mean() : 1;
+
 			// Form an exponential cutoff and apply contribution weights
 			float pdv_contrib = exp((-1)*normalized_pdv) * ZT_PATH_CONTRIB_PDV;
 			float latency_contrib = exp((-1)*normalized_la) * ZT_PATH_CONTRIB_LATENCY;
+
 			// Throughput Disturbance Coefficient
 			float throughput_disturbance_contrib = exp((-1)*throughput_cv) * ZT_PATH_CONTRIB_THROUGHPUT_DISTURBANCE;
-			_throughputDisturbanceSamples->push(throughput_cv);
-			_lastComputedThroughputDistCoeff = _throughputDisturbanceSamples->mean();
+			_throughputDisturbanceSamples.push(throughput_cv);
+			_lastComputedThroughputDistCoeff = _throughputDisturbanceSamples.mean();
+
 			// Obey user-defined ignored contributions
 			pdv_contrib = ZT_PATH_CONTRIB_PDV > 0.0 ? pdv_contrib : 1;
 			latency_contrib = ZT_PATH_CONTRIB_LATENCY > 0.0 ? latency_contrib : 1;
 			throughput_disturbance_contrib = ZT_PATH_CONTRIB_THROUGHPUT_DISTURBANCE > 0.0 ? throughput_disturbance_contrib : 1;
+
 			// Stability
 			_lastComputedStability = pdv_contrib + latency_contrib + throughput_disturbance_contrib;
 			_lastComputedStability *= 1 - _lastComputedPacketErrorRatio;
+
 			// Prevent QoS records from sticking around for too long
 			std::map<uint64_t,uint64_t>::iterator it = _outQoSRecords.begin();
 			while (it != _outQoSRecords.end()) {
@@ -647,18 +645,6 @@ public:
 	 */
 	inline int64_t lastTrustEstablishedPacketReceived() const { return _lastTrustEstablishedPacketReceived; }
 
-	/**
-	 * Initialize statistical buffers
-	 */
-	inline void prepareBuffers() {
-		_throughputSamples = new RingBuffer<uint64_t>(ZT_PATH_QUALITY_METRIC_WIN_SZ);
-		_latencySamples = new RingBuffer<uint32_t>(ZT_PATH_QUALITY_METRIC_WIN_SZ);
-		_packetValiditySamples = new RingBuffer<bool>(ZT_PATH_QUALITY_METRIC_WIN_SZ);
-		_throughputDisturbanceSamples = new RingBuffer<float>(ZT_PATH_QUALITY_METRIC_WIN_SZ);
-		memset(_ifname, 0, 16);
-		memset(_addrString, 0, sizeof(_addrString));
-	}
-
 private:
 	Mutex _statistics_m;
 
@@ -672,9 +658,9 @@ private:
 	InetAddress::IpScope _ipScope; // memoize this since it's a computed value checked often
 	AtomicCounter __refCount;
 
-	std::map<uint64_t, uint64_t> _outQoSRecords; // id:egress_time
-	std::map<uint64_t, uint64_t> _inQoSRecords; // id:now
-	std::map<uint64_t, uint16_t> _inACKRecords; // id:len
+	std::map<uint64_t,uint64_t> _outQoSRecords; // id:egress_time
+	std::map<uint64_t,uint64_t> _inQoSRecords; // id:now
+	std::map<uint64_t,uint16_t> _inACKRecords; // id:len
 
 	int64_t _lastAck;
 	int64_t _lastThroughputEstimation;
@@ -702,16 +688,14 @@ private:
 	float _lastComputedThroughputDistCoeff;
 	unsigned char _lastAllocation;
 
-
-
 	// cached human-readable strings for tracing purposes
 	char _ifname[16];
 	char _addrString[256];
 
-	RingBuffer<uint64_t> *_throughputSamples;
-	RingBuffer<uint32_t> *_latencySamples;
-	RingBuffer<bool> *_packetValiditySamples;
-	RingBuffer<float> *_throughputDisturbanceSamples;
+	RingBuffer<uint64_t,ZT_PATH_QUALITY_METRIC_WIN_SZ> _throughputSamples;
+	RingBuffer<uint32_t,ZT_PATH_QUALITY_METRIC_WIN_SZ> _latencySamples;
+	RingBuffer<bool,ZT_PATH_QUALITY_METRIC_WIN_SZ> _packetValiditySamples;
+	RingBuffer<float,ZT_PATH_QUALITY_METRIC_WIN_SZ> _throughputDisturbanceSamples;
 };
 
 } // namespace ZeroTier

+ 2 - 3
node/Peer.cpp

@@ -76,7 +76,6 @@ Peer::Peer(const RuntimeEnvironment *renv,const Identity &myIdentity,const Ident
 	Utils::getSecureRandom(&_freeRandomByte, 1);
 	if (!myIdentity.agree(peerIdentity,_key,ZT_PEER_SECRET_KEY_LENGTH))
 		throw ZT_EXCEPTION_INVALID_ARGUMENT;
-	_pathChoiceHist = new RingBuffer<int>(ZT_MULTIPATH_PROPORTION_WIN_SZ);
 }
 
 void Peer::received(
@@ -471,7 +470,7 @@ SharedPtr<Path> Peer::getAppropriatePath(int64_t now, bool includeExpired)
 			if (_paths[i].p) {
 				if (rf < _paths[i].p->allocation()) {
 					bestPath = i;
-					_pathChoiceHist->push(bestPath); // Record which path we chose
+					_pathChoiceHist.push(bestPath); // Record which path we chose
 					break;
 				}
 				rf -= _paths[i].p->allocation();
@@ -500,7 +499,7 @@ char *Peer::interfaceListStr()
 			float targetAllocation = 1.0 / alivePathCount;
 			float currentAllocation = 1.0;
 			if (alivePathCount > 1) {
-				currentAllocation = (float)_pathChoiceHist->countValue(i) / (float)_pathChoiceHist->count();
+				currentAllocation = (float)_pathChoiceHist.countValue(i) / (float)_pathChoiceHist.count();
 				if (fabs(targetAllocation - currentAllocation) > ZT_PATH_IMBALANCE_THRESHOLD) {
 					imbalanced = true;
 				}

+ 2 - 6
node/Peer.hpp

@@ -60,11 +60,7 @@ private:
 	Peer() {} // disabled to prevent bugs -- should not be constructed uninitialized
 
 public:
-	~Peer() {
-		Utils::burn(_key,sizeof(_key));
-		delete _pathChoiceHist;
-		_pathChoiceHist = NULL;
-	}
+	~Peer() { Utils::burn(_key,sizeof(_key)); }
 
 	/**
 	 * Construct a new peer
@@ -674,7 +670,7 @@ private:
 
 	AtomicCounter __refCount;
 
-	RingBuffer<int> *_pathChoiceHist;
+	RingBuffer<int,ZT_MULTIPATH_PROPORTION_WIN_SZ> _pathChoiceHist;
 
 	bool _linkIsBalanced;
 	bool _linkIsRedundant;

+ 4 - 117
node/Poly1305.cpp

@@ -18,115 +18,6 @@ Public domain.
 
 namespace ZeroTier {
 
-#if 0
-
-// "Naive" implementation, which is slower... might still want this on some older
-// or weird platforms if the later versions have issues.
-
-static inline void add(unsigned int h[17],const unsigned int c[17])
-{
-  unsigned int j;
-  unsigned int u;
-  u = 0;
-  for (j = 0;j < 17;++j) { u += h[j] + c[j]; h[j] = u & 255; u >>= 8; }
-}
-
-static inline void squeeze(unsigned int h[17])
-{
-  unsigned int j;
-  unsigned int u;
-  u = 0;
-  for (j = 0;j < 16;++j) { u += h[j]; h[j] = u & 255; u >>= 8; }
-  u += h[16]; h[16] = u & 3;
-  u = 5 * (u >> 2);
-  for (j = 0;j < 16;++j) { u += h[j]; h[j] = u & 255; u >>= 8; }
-  u += h[16]; h[16] = u;
-}
-
-static const unsigned int minusp[17] = {
-  5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252
-} ;
-
-static inline void freeze(unsigned int h[17])
-{
-  unsigned int horig[17];
-  unsigned int j;
-  unsigned int negative;
-  for (j = 0;j < 17;++j) horig[j] = h[j];
-  add(h,minusp);
-  negative = -(h[16] >> 7);
-  for (j = 0;j < 17;++j) h[j] ^= negative & (horig[j] ^ h[j]);
-}
-
-static inline void mulmod(unsigned int h[17],const unsigned int r[17])
-{
-  unsigned int hr[17];
-  unsigned int i;
-  unsigned int j;
-  unsigned int u;
-
-  for (i = 0;i < 17;++i) {
-    u = 0;
-    for (j = 0;j <= i;++j) u += h[j] * r[i - j];
-    for (j = i + 1;j < 17;++j) u += 320 * h[j] * r[i + 17 - j];
-    hr[i] = u;
-  }
-  for (i = 0;i < 17;++i) h[i] = hr[i];
-  squeeze(h);
-}
-
-static inline int crypto_onetimeauth(unsigned char *out,const unsigned char *in,unsigned long long inlen,const unsigned char *k)
-{
-  unsigned int j;
-  unsigned int r[17];
-  unsigned int h[17];
-  unsigned int c[17];
-
-  r[0] = k[0];
-  r[1] = k[1];
-  r[2] = k[2];
-  r[3] = k[3] & 15;
-  r[4] = k[4] & 252;
-  r[5] = k[5];
-  r[6] = k[6];
-  r[7] = k[7] & 15;
-  r[8] = k[8] & 252;
-  r[9] = k[9];
-  r[10] = k[10];
-  r[11] = k[11] & 15;
-  r[12] = k[12] & 252;
-  r[13] = k[13];
-  r[14] = k[14];
-  r[15] = k[15] & 15;
-  r[16] = 0;
-
-  for (j = 0;j < 17;++j) h[j] = 0;
-
-  while (inlen > 0) {
-    for (j = 0;j < 17;++j) c[j] = 0;
-    for (j = 0;(j < 16) && (j < inlen);++j) c[j] = in[j];
-    c[j] = 1;
-    in += j; inlen -= j;
-    add(h,c);
-    mulmod(h,r);
-  }
-
-  freeze(h);
-
-  for (j = 0;j < 16;++j) c[j] = k[j + 16];
-  c[16] = 0;
-  add(h,c);
-  for (j = 0;j < 16;++j) out[j] = h[j];
-  return 0;
-}
-
-void Poly1305::compute(void *auth,const void *data,unsigned int len,const void *key)
-{
-	crypto_onetimeauth((unsigned char *)auth,(const unsigned char *)data,len,(const unsigned char *)key);
-}
-
-#endif
-
 namespace {
 
 typedef struct poly1305_context {
@@ -215,8 +106,7 @@ static inline void U64TO8(unsigned char *p, unsigned long long v)
 #define U64TO8(p,v) ((*reinterpret_cast<unsigned long long *>(p)) = (v))
 #endif
 
-static inline void
-poly1305_init(poly1305_context *ctx, const unsigned char key[32]) {
+static inline void poly1305_init(poly1305_context *ctx, const unsigned char key[32]) {
   poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
   unsigned long long t0,t1;
 
@@ -241,8 +131,7 @@ poly1305_init(poly1305_context *ctx, const unsigned char key[32]) {
   st->final = 0;
 }
 
-static inline void
-poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) {
+static inline void poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) {
   const unsigned long long hibit = (st->final) ? 0 : ((unsigned long long)1 << 40); /* 1 << 128 */
   unsigned long long r0,r1,r2;
   unsigned long long s1,s2;
@@ -293,8 +182,7 @@ poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t by
   st->h[2] = h2;
 }
 
-static inline void
-poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) {
+static inline void poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) {
   poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
   unsigned long long h0,h1,h2,c;
   unsigned long long g0,g1,g2;
@@ -582,8 +470,7 @@ poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) {
 
 #endif // MSC/GCC or not
 
-static inline void
-poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes) {
+static inline void poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes) {
   poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx;
   size_t i;
 

+ 52 - 70
node/RingBuffer.hpp

@@ -47,40 +47,28 @@ namespace ZeroTier {
  * to reduce the complexity of code needed to interact with this type of buffer.
  */
 
-template <class T>
+template <class T,size_t S>
 class RingBuffer
 {
 private:
-	T * buf;
-	size_t size;
+	T buf[S];
 	size_t begin;
 	size_t end;
 	bool wrap;
 
 public:
-
-	/**
-	 * create a RingBuffer with space for up to size elements.
-	 */
-	explicit RingBuffer(size_t size)
-		: size(size),
+	RingBuffer() :
 		begin(0),
 		end(0),
 		wrap(false)
 	{
-		buf = new T[size];
-		memset(buf, 0, sizeof(T) * size);
-	}
-
-	~RingBuffer()
-	{
-		delete [] buf;
+		memset(buf,0,sizeof(T)*S);
 	}
 
 	/**
 	 * @return A pointer to the underlying buffer
 	 */
-	T* get_buf()
+	inline T *get_buf()
 	{
 		return buf + begin;
 	}
@@ -90,17 +78,17 @@ public:
 	 * @param n Number of elements to copy in
 	 * @return Number of elements we copied in
 	 */
-	size_t produce(size_t n)
+	inline size_t produce(size_t n)
 	{
 		n = std::min(n, getFree());
 		if (n == 0) {
 			return n;
 		}
-		const size_t first_chunk = std::min(n, size - end);
-		end = (end + first_chunk) % size;
+		const size_t first_chunk = std::min(n, S - end);
+		end = (end + first_chunk) % S;
 		if (first_chunk < n) {
 			const size_t second_chunk = n - first_chunk;
-			end = (end + second_chunk) % size;
+			end = (end + second_chunk) % S;
 		}
 		if (begin == end) {
 			wrap = true;
@@ -112,17 +100,14 @@ public:
 	 * Fast erase, O(1). 
 	 * Merely reset the buffer pointer, doesn't erase contents
 	 */
-	void reset()
-	{
-		consume(count());
-	}
+	inline void reset() { consume(count()); }
 
 	/** 
 	 * adjust buffer index pointer as if we copied data out
 	 * @param n Number of elements we copied from the buffer
 	 * @return Number of elements actually available from the buffer
 	 */
-	size_t consume(size_t n)
+	inline size_t consume(size_t n)
 	{
 		n = std::min(n, count());
 		if (n == 0) {
@@ -131,11 +116,11 @@ public:
 		if (wrap) {
 			wrap = false;
 		}
-		const size_t first_chunk = std::min(n, size - begin);
-		begin = (begin + first_chunk) % size;
+		const size_t first_chunk = std::min(n, S - begin);
+		begin = (begin + first_chunk) % S;
 		if (first_chunk < n) {
 			const size_t second_chunk = n - first_chunk;
-			begin = (begin + second_chunk) % size;
+			begin = (begin + second_chunk) % S;
 		}
 		return n;
 	}
@@ -144,19 +129,19 @@ public:
 	 * @param data Buffer that is to be written to the ring
 	 * @param n Number of elements to write to the buffer
 	 */
-	size_t write(const T * data, size_t n)
+	inline size_t write(const T * data, size_t n)
 	{
 		n = std::min(n, getFree());
 		if (n == 0) {
 			return n;
 		}
-		const size_t first_chunk = std::min(n, size - end);
+		const size_t first_chunk = std::min(n, S - end);
 		memcpy(buf + end, data, first_chunk * sizeof(T));
-		end = (end + first_chunk) % size;
+		end = (end + first_chunk) % S;
 		if (first_chunk < n) {
 			const size_t second_chunk = n - first_chunk;
 			memcpy(buf + end, data + first_chunk, second_chunk * sizeof(T));
-			end = (end + second_chunk) % size;
+			end = (end + second_chunk) % S;
 		}
 		if (begin == end) {
 			wrap = true;
@@ -169,14 +154,14 @@ public:
 	 *
 	 * @param value A single value to be placed in the buffer
 	 */
-	void push(const T value)
+	inline void push(const T value)
 	{
-		if (count() == size) {
+		if (count() == S) {
 			consume(1);
 		}
-		const size_t first_chunk = std::min((size_t)1, size - end);
+		const size_t first_chunk = std::min((size_t)1, S - end);
 		*(buf + end) = value;
-		end = (end + first_chunk) % size;
+		end = (end + first_chunk) % S;
 		if (begin == end) {
 			wrap = true;
 		}
@@ -185,14 +170,14 @@ public:
 	/**
 	 * @return The most recently pushed element on the buffer
 	 */
-	T get_most_recent() { return *(buf + end); }
+	inline T get_most_recent() { return *(buf + end); }
 
 	/**
 	 * @param dest Destination buffer
 	 * @param n Size (in terms of number of elements) of the destination buffer
 	 * @return Number of elements read from the buffer
 	 */
-	size_t read(T * dest, size_t n)
+	inline size_t read(T *dest,size_t n)
 	{
 		n = std::min(n, count());
 		if (n == 0) {
@@ -201,13 +186,13 @@ public:
 		if (wrap) {
 			wrap = false;
 		}
-		const size_t first_chunk = std::min(n, size - begin);
+		const size_t first_chunk = std::min(n, S - begin);
 		memcpy(dest, buf + begin, first_chunk * sizeof(T));
-		begin = (begin + first_chunk) % size;
+		begin = (begin + first_chunk) % S;
 		if (first_chunk < n) {
 			const size_t second_chunk = n - first_chunk;
 			memcpy(dest + first_chunk, buf + begin, second_chunk * sizeof(T));
-			begin = (begin + second_chunk) % size;
+			begin = (begin + second_chunk) % S;
 		}
 		return n;
 	}
@@ -217,34 +202,34 @@ public:
 	 *
 	 * @return The number of elements in the buffer
 	 */
-	size_t count()
+	inline size_t count()
 	{
 		if (end == begin) {
-			return wrap ? size : 0;
+			return wrap ? S : 0;
 		}
 		else if (end > begin) {
 			return end - begin;
 		}
 		else {
-			return size + end - begin;
+			return S + end - begin;
 		}
 	}
 
 	/**
 	 * @return The number of slots that are unused in the buffer
 	 */
-	size_t getFree() { return size - count(); }
+	inline size_t getFree() { return S - count(); }
 
 	/**
 	 * @return The arithmetic mean of the contents of the buffer
 	 */
-	float mean()
+	inline float mean()
 	{
 		size_t iterator = begin;
 		float subtotal = 0;
 		size_t curr_cnt = count();
 		for (size_t i=0; i<curr_cnt; i++) {
-			iterator = (iterator + size - 1) % curr_cnt;
+			iterator = (iterator + S - 1) % curr_cnt;
 			subtotal += (float)*(buf + iterator);
 		}
 		return curr_cnt ? subtotal / (float)curr_cnt : 0;
@@ -253,14 +238,14 @@ public:
 	/**
 	 * @return The arithmetic mean of the most recent 'n' elements of the buffer
 	 */
-	float mean(size_t n)
+	inline float mean(size_t n)
 	{
-		n = n < size ? n : size;
+		n = n < S ? n : S;
 		size_t iterator = begin;
 		float subtotal = 0;
 		size_t curr_cnt = count();
 		for (size_t i=0; i<n; i++) {
-			iterator = (iterator + size - 1) % curr_cnt;
+			iterator = (iterator + S - 1) % curr_cnt;
 			subtotal += (float)*(buf + iterator);
 		}
 		return curr_cnt ? subtotal / (float)curr_cnt : 0;
@@ -269,39 +254,36 @@ public:
 	/**
 	 * @return The sample standard deviation of element values
 	 */
-	float stddev() { return sqrt(variance()); }
+	inline float stddev() { return sqrt(variance()); }
 
 	/**
 	 * @return The variance of element values
 	 */
-	float variance()
+	inline float variance()
 	{
 		size_t iterator = begin;
 		float cached_mean = mean();
 		size_t curr_cnt = count();
-		if (size) {
-			T sum_of_squared_deviations = 0;
-			for (size_t i=0; i<curr_cnt; i++) {
-				iterator = (iterator + size - 1) % curr_cnt;
-				float deviation = (buf[i] - cached_mean);
-				sum_of_squared_deviations += (deviation*deviation);
-			}
-			float variance = (float)sum_of_squared_deviations / (float)(size - 1);
-			return variance;
+		T sum_of_squared_deviations = 0;
+		for (size_t i=0; i<curr_cnt; i++) {
+			iterator = (iterator + S - 1) % curr_cnt;
+			float deviation = (buf[i] - cached_mean);
+			sum_of_squared_deviations += (deviation*deviation);
 		}
-		return 0;
+		float variance = (float)sum_of_squared_deviations / (float)(S - 1);
+		return variance;
 	}
 
 	/**
 	 * @return The number of elements of zero value
 	 */
-	size_t zeroCount()
+	inline size_t zeroCount()
 	{
 		size_t iterator = begin;
 		size_t zeros = 0;
 		size_t curr_cnt = count();
 		for (size_t i=0; i<curr_cnt; i++) {
-			iterator = (iterator + size - 1) % curr_cnt;
+			iterator = (iterator + S - 1) % curr_cnt;
 			if (*(buf + iterator) == 0) {
 				zeros++;
 			}
@@ -313,13 +295,13 @@ public:
 	 * @param value Value to match against in buffer
 	 * @return The number of values held in the ring buffer which match a given value
 	 */
-	size_t countValue(T value)
+	inline size_t countValue(T value)
 	{
 		size_t iterator = begin;
 		size_t cnt = 0;
 		size_t curr_cnt = count();
 		for (size_t i=0; i<curr_cnt; i++) {
-			iterator = (iterator + size - 1) % curr_cnt;
+			iterator = (iterator + S - 1) % curr_cnt;
 			if (*(buf + iterator) == value) {
 				cnt++;
 			}
@@ -330,11 +312,11 @@ public:
 	/**
 	 * Print the contents of the buffer
 	 */
-	void dump()
+	inline void dump()
 	{
 		size_t iterator = begin;
-		for (size_t i=0; i<size; i++) {
-			iterator = (iterator + size - 1) % size;
+		for (size_t i=0; i<S; i++) {
+			iterator = (iterator + S - 1) % S;
 			if (typeid(T) == typeid(int)) {
 				 //DEBUG_INFO("buf[%2zu]=%2d", iterator, (int)*(buf + iterator));
 			}

+ 4 - 4
node/Utils.hpp

@@ -267,10 +267,10 @@ public:
 
 	static inline float normalize(float value, int64_t bigMin, int64_t bigMax, int32_t targetMin, int32_t targetMax)
 	{
-	    int64_t bigSpan = bigMax - bigMin;
-	    int64_t smallSpan = targetMax - targetMin;
-	    float valueScaled = (value - (float)bigMin) / (float)bigSpan;
-	    return (float)targetMin + valueScaled * (float)smallSpan;
+		int64_t bigSpan = bigMax - bigMin;
+		int64_t smallSpan = targetMax - targetMin;
+		float valueScaled = (value - (float)bigMin) / (float)bigSpan;
+		return (float)targetMin + valueScaled * (float)smallSpan;
 	}
 
 	/**