var _ = require('underscore'); var assert = require('chai').assert; var gutil = require('app/common/gutil'); var utils = require('../utils'); /** * Set env ENABLE_TIMING_TESTS=1 to run the timing tests. * These tests rely on mocha's reported timings to allow you to compare the performance of * different implementations. */ var ENABLE_TIMING_TESTS = Boolean(process.env.ENABLE_TIMING_TESTS); //---------------------------------------------------------------------- // Following recommendations such as here: // http://stackoverflow.com/questions/7032550/javascript-insert-an-array-inside-another-array // However, this won't work for large arrToInsert because .apply has a limit on length of args. function spliceApplyConcat(target, start, arrToInsert) { target.splice.apply(target, [start, 0].concat(arrToInsert)); return target; } //---------------------------------------------------------------------- // Seems like could be faster, but disturbingly mutates the last argument. // However, this won't work for large arrToInsert because .apply has a limit on length of args. function spliceApplyUnshift(target, start, arrToInsert) { var spliceArgs = arrToInsert; spliceArgs.unshift(start, 0); try { target.splice.apply(target, spliceArgs); } finally { spliceArgs.splice(0, 2); } return target; } //---------------------------------------------------------------------- // This is from the same stackoverflow answer, but builds a new array instead of mutating target. function nonSpliceUsingSlice(target, start, arrToInsert) { return target.slice(0, start).concat(arrToInsert, target.slice(start)); } //---------------------------------------------------------------------- // A simple manual implementation, that performs reasonably well in all environments. function spliceManualWithTailCopy(target, start, arrToInsert) { var insLen = arrToInsert.length; if (insLen === 1) { target.splice(start, 0, arrToInsert[0]); } else if (insLen > 1) { var i, len, tail = target.slice(start); for (i = 0; i < insLen; i++, start++) { target[start] = arrToInsert[i]; } for (i = 0, len = tail.length; i < len; i++, start++) { target[start] = tail[i]; } } return target; } //---------------------------------------------------------------------- function spliceCopyWithTail(helpers) { var copyForward = helpers.copyForward; return function(target, start, arrToInsert) { var tail = target.slice(start), insLen = arrToInsert.length; copyForward(target, start, arrToInsert, 0, insLen); copyForward(target, start + insLen, tail, 0, tail.length); return target; }; } //---------------------------------------------------------------------- // This implementation avoids creating a copy of the tail, but fills in the array // non-contiguously. function spliceFwdBackCopy(helpers) { var copyForward = helpers.copyForward, copyBackward = helpers.copyBackward; return function(target, start, arrayToInsert) { var count = arrayToInsert.length; copyBackward(target, start + count, target, start, target.length - start); copyForward(target, start, arrayToInsert, 0, count); return target; }; } //---------------------------------------------------------------------- // This implementation tries to be smarter by avoiding allocations, appending to the array // contiguously, then filling in the gap. function spliceAppendCopy(helpers) { var appendFunc = helpers.append, copyForward = helpers.copyForward, copyBackward = helpers.copyBackward; return function(target, start, arrToInsert) { var origLen = target.length; var tailLen = origLen - start; var insLen = arrToInsert.length; if (insLen > tailLen) { appendFunc(target, arrToInsert, tailLen, insLen - tailLen); appendFunc(target, target, start, tailLen); copyForward(target, start, arrToInsert, 0, tailLen); } else { appendFunc(target, target, origLen - insLen, insLen); copyBackward(target, start + insLen, target, start, tailLen - insLen); copyForward(target, start, arrToInsert, 0, insLen); } return target; }; } //---------------------------------------------------------------------- // This implementation only appends, but requires splicing out the tail from the original. // It is consistently slower on Node. function spliceAppendOnly(helpers) { var appendFunc = helpers.append; return function(target, start, arrToInsert) { var tail = target.splice(start, target.length); appendFunc(target, arrToInsert, 0, arrToInsert.length); appendFunc(target, tail, 0, tail.length); return target; }; } //---------------------------------------------------------------------- // COPY-FORWARD FUNCTIONS //---------------------------------------------------------------------- var copyForward = { gutil: gutil.arrayCopyForward, copyForward1: function(toArray, toStart, fromArray, fromStart, count) { for (var end = toStart + count; toStart < end; ++toStart, ++fromStart) { toArray[toStart] = fromArray[fromStart]; } }, copyForward8: function(toArray, toStart, fromArray, fromStart, count) { var end = toStart + count; for (var xend = end - 7; toStart < xend; fromStart += 8, toStart += 8) { toArray[toStart] = fromArray[fromStart]; toArray[toStart+1] = fromArray[fromStart+1]; toArray[toStart+2] = fromArray[fromStart+2]; toArray[toStart+3] = fromArray[fromStart+3]; toArray[toStart+4] = fromArray[fromStart+4]; toArray[toStart+5] = fromArray[fromStart+5]; toArray[toStart+6] = fromArray[fromStart+6]; toArray[toStart+7] = fromArray[fromStart+7]; } for (; toStart < end; ++fromStart, ++toStart) { toArray[toStart] = fromArray[fromStart]; } }, copyForward64: function(toArray, toStart, fromArray, fromStart, count) { var end = toStart + count; for (var xend = end - 63; toStart < xend; fromStart += 64, toStart += 64) { toArray[toStart]=fromArray[fromStart]; toArray[toStart+1]=fromArray[fromStart+1]; toArray[toStart+2]=fromArray[fromStart+2]; toArray[toStart+3]=fromArray[fromStart+3]; toArray[toStart+4]=fromArray[fromStart+4]; toArray[toStart+5]=fromArray[fromStart+5]; toArray[toStart+6]=fromArray[fromStart+6]; toArray[toStart+7]=fromArray[fromStart+7]; toArray[toStart+8]=fromArray[fromStart+8]; toArray[toStart+9]=fromArray[fromStart+9]; toArray[toStart+10]=fromArray[fromStart+10]; toArray[toStart+11]=fromArray[fromStart+11]; toArray[toStart+12]=fromArray[fromStart+12]; toArray[toStart+13]=fromArray[fromStart+13]; toArray[toStart+14]=fromArray[fromStart+14]; toArray[toStart+15]=fromArray[fromStart+15]; toArray[toStart+16]=fromArray[fromStart+16]; toArray[toStart+17]=fromArray[fromStart+17]; toArray[toStart+18]=fromArray[fromStart+18]; toArray[toStart+19]=fromArray[fromStart+19]; toArray[toStart+20]=fromArray[fromStart+20]; toArray[toStart+21]=fromArray[fromStart+21]; toArray[toStart+22]=fromArray[fromStart+22]; toArray[toStart+23]=fromArray[fromStart+23]; toArray[toStart+24]=fromArray[fromStart+24]; toArray[toStart+25]=fromArray[fromStart+25]; toArray[toStart+26]=fromArray[fromStart+26]; toArray[toStart+27]=fromArray[fromStart+27]; toArray[toStart+28]=fromArray[fromStart+28]; toArray[toStart+29]=fromArray[fromStart+29]; toArray[toStart+30]=fromArray[fromStart+30]; toArray[toStart+31]=fromArray[fromStart+31]; toArray[toStart+32]=fromArray[fromStart+32]; toArray[toStart+33]=fromArray[fromStart+33]; toArray[toStart+34]=fromArray[fromStart+34]; toArray[toStart+35]=fromArray[fromStart+35]; toArray[toStart+36]=fromArray[fromStart+36]; toArray[toStart+37]=fromArray[fromStart+37]; toArray[toStart+38]=fromArray[fromStart+38]; toArray[toStart+39]=fromArray[fromStart+39]; toArray[toStart+40]=fromArray[fromStart+40]; toArray[toStart+41]=fromArray[fromStart+41]; toArray[toStart+42]=fromArray[fromStart+42]; toArray[toStart+43]=fromArray[fromStart+43]; toArray[toStart+44]=fromArray[fromStart+44]; toArray[toStart+45]=fromArray[fromStart+45]; toArray[toStart+46]=fromArray[fromStart+46]; toArray[toStart+47]=fromArray[fromStart+47]; toArray[toStart+48]=fromArray[fromStart+48]; toArray[toStart+49]=fromArray[fromStart+49]; toArray[toStart+50]=fromArray[fromStart+50]; toArray[toStart+51]=fromArray[fromStart+51]; toArray[toStart+52]=fromArray[fromStart+52]; toArray[toStart+53]=fromArray[fromStart+53]; toArray[toStart+54]=fromArray[fromStart+54]; toArray[toStart+55]=fromArray[fromStart+55]; toArray[toStart+56]=fromArray[fromStart+56]; toArray[toStart+57]=fromArray[fromStart+57]; toArray[toStart+58]=fromArray[fromStart+58]; toArray[toStart+59]=fromArray[fromStart+59]; toArray[toStart+60]=fromArray[fromStart+60]; toArray[toStart+61]=fromArray[fromStart+61]; toArray[toStart+62]=fromArray[fromStart+62]; toArray[toStart+63]=fromArray[fromStart+63]; } for (; toStart < end; ++fromStart, ++toStart) { toArray[toStart] = fromArray[fromStart]; } } }; //---------------------------------------------------------------------- // COPY-BACKWARD FUNCTIONS //---------------------------------------------------------------------- var copyBackward = { gutil: gutil.arrayCopyBackward, copyBackward1: function(toArray, toStart, fromArray, fromStart, count) { for (var i = toStart + count - 1, j = fromStart + count - 1; i >= toStart; --i, --j) { toArray[i] = fromArray[j]; } }, copyBackward8: function(toArray, toStart, fromArray, fromStart, count) { var i = toStart + count - 1, j = fromStart + count - 1; for (var xStart = toStart + 7; i >= xStart; i -= 8, j -= 8) { toArray[i] = fromArray[j]; toArray[i-1] = fromArray[j-1]; toArray[i-2] = fromArray[j-2]; toArray[i-3] = fromArray[j-3]; toArray[i-4] = fromArray[j-4]; toArray[i-5] = fromArray[j-5]; toArray[i-6] = fromArray[j-6]; toArray[i-7] = fromArray[j-7]; } for ( ; i >= toStart; --i, --j) { toArray[i] = fromArray[j]; } }, copyBackward64: function(toArray, toStart, fromArray, fromStart, count) { var i = toStart + count - 1, j = fromStart + count - 1; for (var xStart = toStart + 63; i >= xStart; i -= 64, j -= 64) { toArray[i]=fromArray[j]; toArray[i-1]=fromArray[j-1]; toArray[i-2]=fromArray[j-2]; toArray[i-3]=fromArray[j-3]; toArray[i-4]=fromArray[j-4]; toArray[i-5]=fromArray[j-5]; toArray[i-6]=fromArray[j-6]; toArray[i-7]=fromArray[j-7]; toArray[i-8]=fromArray[j-8]; toArray[i-9]=fromArray[j-9]; toArray[i-10]=fromArray[j-10]; toArray[i-11]=fromArray[j-11]; toArray[i-12]=fromArray[j-12]; toArray[i-13]=fromArray[j-13]; toArray[i-14]=fromArray[j-14]; toArray[i-15]=fromArray[j-15]; toArray[i-16]=fromArray[j-16]; toArray[i-17]=fromArray[j-17]; toArray[i-18]=fromArray[j-18]; toArray[i-19]=fromArray[j-19]; toArray[i-20]=fromArray[j-20]; toArray[i-21]=fromArray[j-21]; toArray[i-22]=fromArray[j-22]; toArray[i-23]=fromArray[j-23]; toArray[i-24]=fromArray[j-24]; toArray[i-25]=fromArray[j-25]; toArray[i-26]=fromArray[j-26]; toArray[i-27]=fromArray[j-27]; toArray[i-28]=fromArray[j-28]; toArray[i-29]=fromArray[j-29]; toArray[i-30]=fromArray[j-30]; toArray[i-31]=fromArray[j-31]; toArray[i-32]=fromArray[j-32]; toArray[i-33]=fromArray[j-33]; toArray[i-34]=fromArray[j-34]; toArray[i-35]=fromArray[j-35]; toArray[i-36]=fromArray[j-36]; toArray[i-37]=fromArray[j-37]; toArray[i-38]=fromArray[j-38]; toArray[i-39]=fromArray[j-39]; toArray[i-40]=fromArray[j-40]; toArray[i-41]=fromArray[j-41]; toArray[i-42]=fromArray[j-42]; toArray[i-43]=fromArray[j-43]; toArray[i-44]=fromArray[j-44]; toArray[i-45]=fromArray[j-45]; toArray[i-46]=fromArray[j-46]; toArray[i-47]=fromArray[j-47]; toArray[i-48]=fromArray[j-48]; toArray[i-49]=fromArray[j-49]; toArray[i-50]=fromArray[j-50]; toArray[i-51]=fromArray[j-51]; toArray[i-52]=fromArray[j-52]; toArray[i-53]=fromArray[j-53]; toArray[i-54]=fromArray[j-54]; toArray[i-55]=fromArray[j-55]; toArray[i-56]=fromArray[j-56]; toArray[i-57]=fromArray[j-57]; toArray[i-58]=fromArray[j-58]; toArray[i-59]=fromArray[j-59]; toArray[i-60]=fromArray[j-60]; toArray[i-61]=fromArray[j-61]; toArray[i-62]=fromArray[j-62]; toArray[i-63]=fromArray[j-63]; } for ( ; i >= toStart; --i, --j) { toArray[i] = fromArray[j]; } } }; //---------------------------------------------------------------------- // APPEND FUNCTIONS. //---------------------------------------------------------------------- var append = { gutil: gutil.arrayAppend, append1: function(toArray, fromArray, fromStart, count) { var end = fromStart + count; for (var i = fromStart; i < end; i++) { toArray.push(fromArray[i]); } }, appendCopy1: function(toArray, fromArray, fromStart, count) { if (count === 1) { toArray.push(fromArray[fromStart]); } else if (count > 1) { var len = toArray.length; toArray.length = len + count; copyForward.copyForward1(toArray, len, fromArray, fromStart, count); } }, append8: function(toArray, fromArray, fromStart, count) { var end = fromStart + count; for (var xend = end - 7; fromStart < xend; fromStart += 8) { toArray.push( fromArray[fromStart], fromArray[fromStart + 1], fromArray[fromStart + 2], fromArray[fromStart + 3], fromArray[fromStart + 4], fromArray[fromStart + 5], fromArray[fromStart + 6], fromArray[fromStart + 7]); } for ( ; fromStart < end; ++fromStart) { toArray.push(fromArray[fromStart]); } }, append64: function(toArray, fromArray, fromStart, count) { var end = fromStart + count; for (var xend = end - 63; fromStart < xend; fromStart += 64) { toArray.push( fromArray[fromStart], fromArray[fromStart + 1], fromArray[fromStart + 2], fromArray[fromStart + 3], fromArray[fromStart + 4], fromArray[fromStart + 5], fromArray[fromStart + 6], fromArray[fromStart + 7], fromArray[fromStart + 8], fromArray[fromStart + 9], fromArray[fromStart + 10], fromArray[fromStart + 11], fromArray[fromStart + 12], fromArray[fromStart + 13], fromArray[fromStart + 14], fromArray[fromStart + 15], fromArray[fromStart + 16], fromArray[fromStart + 17], fromArray[fromStart + 18], fromArray[fromStart + 19], fromArray[fromStart + 20], fromArray[fromStart + 21], fromArray[fromStart + 22], fromArray[fromStart + 23], fromArray[fromStart + 24], fromArray[fromStart + 25], fromArray[fromStart + 26], fromArray[fromStart + 27], fromArray[fromStart + 28], fromArray[fromStart + 29], fromArray[fromStart + 30], fromArray[fromStart + 31], fromArray[fromStart + 32], fromArray[fromStart + 33], fromArray[fromStart + 34], fromArray[fromStart + 35], fromArray[fromStart + 36], fromArray[fromStart + 37], fromArray[fromStart + 38], fromArray[fromStart + 39], fromArray[fromStart + 40], fromArray[fromStart + 41], fromArray[fromStart + 42], fromArray[fromStart + 43], fromArray[fromStart + 44], fromArray[fromStart + 45], fromArray[fromStart + 46], fromArray[fromStart + 47], fromArray[fromStart + 48], fromArray[fromStart + 49], fromArray[fromStart + 50], fromArray[fromStart + 51], fromArray[fromStart + 52], fromArray[fromStart + 53], fromArray[fromStart + 54], fromArray[fromStart + 55], fromArray[fromStart + 56], fromArray[fromStart + 57], fromArray[fromStart + 58], fromArray[fromStart + 59], fromArray[fromStart + 60], fromArray[fromStart + 61], fromArray[fromStart + 62], fromArray[fromStart + 63] ); } for ( ; fromStart < end; ++fromStart) { toArray.push(fromArray[fromStart]); } }, appendSlice64: function(toArray, fromArray, fromStart, count) { var end = fromStart + count; for ( ; fromStart < end; fromStart += 64) { Array.prototype.push.apply(toArray, fromArray.slice(fromStart, Math.min(fromStart + 64, end))); } } }; //---------------------------------------------------------------------- var helpers1 = { copyForward: copyForward.copyForward1, copyBackward: copyBackward.copyBackward1, append: append.append1, }; var helpers8 = { copyForward: copyForward.copyForward8, copyBackward: copyBackward.copyBackward8, append: append.append8, }; var helpers64 = { copyForward: copyForward.copyForward64, copyBackward: copyBackward.copyBackward64, append: append.append64, }; var allArraySpliceFuncs = { spliceApplyConcat: spliceApplyConcat, spliceApplyUnshift: spliceApplyUnshift, nonSpliceUsingSlice: nonSpliceUsingSlice, spliceGutil: gutil.arraySplice, spliceManualWithTailCopy: spliceManualWithTailCopy, spliceCopyWithTail1: spliceCopyWithTail(helpers1), spliceCopyWithTail8: spliceCopyWithTail(helpers8), spliceCopyWithTail64: spliceCopyWithTail(helpers64), spliceFwdBackCopy1: spliceFwdBackCopy(helpers1), spliceFwdBackCopy8: spliceFwdBackCopy(helpers8), spliceFwdBackCopy64: spliceFwdBackCopy(helpers64), spliceAppendCopy1: spliceAppendCopy(helpers1), spliceAppendCopy8: spliceAppendCopy(helpers8), spliceAppendCopy64: spliceAppendCopy(helpers64), spliceAppendOnly1: spliceAppendOnly(helpers1), spliceAppendOnly8: spliceAppendOnly(helpers8), spliceAppendOnly64: spliceAppendOnly(helpers64), }; var timedArraySpliceFuncs = { // The following two naive implementations cannot cope with large arrays, and raise // "RangeError: Maximum call stack size exceeded". //spliceApplyConcat: spliceApplyConcat, //spliceApplyUnshift: spliceApplyUnshift, // This isn't a real splice, it doesn't modify the array. //nonSpliceUsingSlice: nonSpliceUsingSlice, // The implementations commented out below are the slower ones. spliceGutil: gutil.arraySplice, spliceManualWithTailCopy: spliceManualWithTailCopy, spliceCopyWithTail1: spliceCopyWithTail(helpers1), //spliceCopyWithTail8: spliceCopyWithTail(helpers8), //spliceCopyWithTail64: spliceCopyWithTail(helpers64), //spliceFwdBackCopy1: spliceFwdBackCopy(helpers1), //spliceFwdBackCopy8: spliceFwdBackCopy(helpers8), //spliceFwdBackCopy64: spliceFwdBackCopy(helpers64), spliceAppendCopy1: spliceAppendCopy(helpers1), spliceAppendCopy8: spliceAppendCopy(helpers8), spliceAppendCopy64: spliceAppendCopy(helpers64), //spliceAppendOnly1: spliceAppendOnly(helpers1), //spliceAppendOnly8: spliceAppendOnly(helpers8), //spliceAppendOnly64: spliceAppendOnly(helpers64), }; //---------------------------------------------------------------------- describe("array copy functions", function() { it("copyForward should copy correctly", function() { _.each(copyForward, function(copyFunc, name) { var data = _.range(10000); copyFunc(data, 0, data, 1, 9999); copyFunc(data, 0, data, 1, 9999); assert.equal(data[0], 2); assert.equal(data[1], 3); assert.equal(data[9996], 9998); assert.equal(data[9997], 9999); assert.equal(data[9998], 9999); assert.equal(data[9999], 9999); }); }); it("copyBackward should copy correctly", function() { _.each(copyBackward, function(copyFunc, name) { var data = _.range(10000); copyFunc(data, 1, data, 0, 9999); copyFunc(data, 1, data, 0, 9999); assert.equal(data[0], 0); assert.equal(data[1], 0); assert.equal(data[2], 0); assert.equal(data[3], 1); assert.equal(data[9998], 9996); assert.equal(data[9999], 9997); }); }); it("arrayAppend should append correctly", function() { _.each(append, function(appendFunc, name) { var out = []; var data = _.range(20000); appendFunc(out, data, 100, 1); appendFunc(out, data, 100, 1000); appendFunc(out, data, 100, 10000); assert.deepEqual(out.slice(0, 4), [100, 100, 101, 102]); assert.deepEqual(out.slice(1000, 1004), [1099, 100, 101, 102]); assert.deepEqual(out.slice(11000), [10099]); }); }); // See ENABLE_TIMING_TESTS flag on top of this file. if (ENABLE_TIMING_TESTS) { describe("timing", function() { var a1m = _.range(1000000); describe("copyForward", function() { var reps = 40; _.each(copyForward, function(copyFunc, name) { var b1m = a1m.slice(0); it(name, function() { utils.repeat(reps, copyFunc, b1m, 0, b1m, 1, 999999); // Make sure it actually worked. These checks shouldn't affect timings much. assert.deepEqual(b1m.slice(0, 10), _.range(reps, reps + 10)); assert.equal(b1m[999999-reps-1], 999998); assert.equal(b1m[999999-reps], 999999); assert.deepEqual(b1m.slice(1000000-reps), _.times(reps, _.constant(999999))); }); }); }); describe("copyBackward", function() { var reps = 40; _.each(copyBackward, function(copyFunc, name) { var b1m = a1m.slice(0); it(name, function() { utils.repeat(reps, copyFunc, b1m, 1, b1m, 0, 999999); // Make sure it actually worked. These checks shouldn't affect timings much. assert.deepEqual(b1m.slice(0, reps), _.times(reps, _.constant(0))); assert.equal(b1m[reps], 0); assert.equal(b1m[reps + 1], 1); assert.deepEqual(b1m.slice(999990), _.range(999990-reps, 1000000-reps)); }); }); }); describe("append", function() { var data = _.range(1000000); function chunkedAppend(appendFunc, data, chunk) { var out = []; var count = data.length / chunk; for (var i = 0; i < count; i++) { appendFunc(out, data, i * chunk, chunk); } return out; } _.each(append, function(appendFunc, name) { it(name, function() { var out1 = chunkedAppend(appendFunc, data, 1); var out2 = chunkedAppend(appendFunc, data, 1000); var out3 = chunkedAppend(appendFunc, data, 1000000); // Make sure it actually worked. Keep the checks short to avoid affecting timings. assert.deepEqual(out1.slice(0, 10), data.slice(0, 10)); assert.deepEqual(out1.slice(data.length - 10), data.slice(data.length - 10)); assert.deepEqual(out2.slice(0, 10), data.slice(0, 10)); assert.deepEqual(out2.slice(data.length - 10), data.slice(data.length - 10)); assert.deepEqual(out3.slice(0, 10), data.slice(0, 10)); assert.deepEqual(out3.slice(data.length - 10), data.slice(data.length - 10)); }); }); }); }); } }); describe('arraySplice', function() { // Make sure all our functions produce the same results as spliceApplyConcat for simple cases. var refSpliceFunc = spliceApplyConcat; it("all candidate functions should be correct for simpler cases", function() { _.each(allArraySpliceFuncs, function(spliceFunc, name) { var a10 = _.range(10), a100 = _.range(100); function checkSpliceFunc(target, start, arrToInsert) { assert.deepEqual(spliceFunc(target.slice(0), start, arrToInsert), refSpliceFunc(target.slice(0), start, arrToInsert), "splice function incorrect for " + name); } checkSpliceFunc(a10, 5, a100); checkSpliceFunc(a100, 50, a10); checkSpliceFunc(a100, 90, a10); checkSpliceFunc(a100, 0, a10); checkSpliceFunc(a100, 100, a10); checkSpliceFunc(a10, 0, a100); checkSpliceFunc(a10, 10, a100); checkSpliceFunc(a10, 1, a10); checkSpliceFunc(a10, 5, a10); checkSpliceFunc(a10, 5, []); assert.deepEqual(spliceFunc(a10.slice(0), 5, a10), [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9]); }); }); // See ENABLE_TIMING_TESTS flag on top of this file. if (ENABLE_TIMING_TESTS) { describe("timing", function() { var a1 = _.range(1); var a1k = _.range(1000); var a1m = _.range(1000000); describe("insert-one", function() { _.each(timedArraySpliceFuncs, function(spliceFunc, name) { var b1m = a1m.slice(0); it(name, function() { utils.repeat(40, spliceFunc, b1m, 500000, a1); }); }); }); describe("insert-1k", function() { _.each(timedArraySpliceFuncs, function(spliceFunc, name) { var b1m = a1m.slice(0); it(name, function() { utils.repeat(40, spliceFunc, b1m, 500000, a1k); }); }); }); describe("insert-1m", function() { _.each(timedArraySpliceFuncs, function(spliceFunc, name) { var b1m = a1m.slice(0); it(name, function() { utils.repeat(4, spliceFunc, b1m, 500000, a1m); }); }); }); }); } });