From 83c9f945cf36986e0ef3b39071536301c2317aa5 Mon Sep 17 00:00:00 2001 From: Erayd Date: Thu, 29 Sep 2016 15:28:55 +1300 Subject: [PATCH] The iterator for `arguments` sucks - refactor to avoid calling it The `arguments` iterator is extremely slow, and as such adds a significant amount of overhead when called in the middle of a hot loop. Manually iterating instead results in a large performance gain, and avoiding the arguments object entirely for the first value gains a little more. --- spique.js | 60 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/spique.js b/spique.js index e248825..005a7d2 100644 --- a/spique.js +++ b/spique.js @@ -45,38 +45,46 @@ function Spique(maxItems, ringSize) { }; // push item(s) onto the end of the buffer - this.enqueue = this.push = function() { - for(var value of arguments) { - if(items >= maxItems) + this.enqueue = this.push = function push(value) { + if(items >= maxItems) + return new Error('Buffer is full'); + // add another ring if necessary + if(!lastRing.available()) { + var newRing = allocateRing(); + lastRing.nextRing = newRing; + newRing.prevRing = lastRing; + lastRing = newRing; + rings++; + } + lastRing.push(value); + items++; + + // process variadic args + for(var argIndex = 1; argIndex < arguments.length; argIndex++) { + if(push(arguments[argIndex])) return new Error('Buffer is full'); - // add another ring if necessary - if(!lastRing.available()) { - var newRing = allocateRing(); - lastRing.nextRing = newRing; - newRing.prevRing = lastRing; - lastRing = newRing; - rings++; - } - lastRing.push(value); - items++; } } // push item(s) onto the start of the buffer - this.unshift = function(value) { - for(var value of arguments) { - if(items >= maxItems) + this.unshift = function unshift(value) { + if(items >= maxItems) + return new Error('Buffer is full'); + // add another ring if necessary + if(!firstRing.available()) { + var newRing = allocateRing(); + newRing.nextRing = firstRing; + firstRing.prevRing = newRing; + firstRing = newRing; + rings++; + } + firstRing.unshift(value); + items++; + + // process variadic args + for(var argIndex = 1; argIndex < arguments.length; argIndex++) { + if(unshift(arguments[argIndex])) return new Error('Buffer is full'); - // add another ring if necessary - if(!firstRing.available()) { - var newRing = allocateRing(); - newRing.nextRing = firstRing; - firstRing.prevRing = newRing; - firstRing = newRing; - rings++; - } - firstRing.unshift(value); - items++; } }