Judging by this question (Is there a max number of arguments JavaScript functions can accept?), the maximum number of arguments you could safely append at one time would be about 100,000
say. Assuming you have the memory to have a duplicate list of 100,000 items at a time you could use the slicing method displayed below. (See the Splice and Apply methods detailed below)
However, I added benchmarking comparisons to the individual push method in different forms to see if there's any performance benefit in doing this since under the hood it's likely the splice concatenation is still element-wise rather than a bulk memcpy operation.
const x = [];
for (let i = 0; i < 10000000; i += 1) {
x.push(i);
}
const a = x.slice();
const b = x.slice();
const v = x.slice();
const y = x.slice();
const z = x.slice();
// append 100,000 at a time using splice
const sliceStart = new Date();
for (let i = 0; i < b.length; i += 100000) {
const len = (i + 100000) % (b.length + 1);
const c = b.slice(i, len);
a.splice(a.length, 0, ...c);
}
const sliceEnd = new Date();
// append 100,000 using Array.prototype.push
const protoStart = new Date();
for (let i = 0; i < b.length; i += 100000) {
const len = (i + 100000) % (b.length + 1);
const c = b.slice(i, len);
Array.prototype.push.apply(v, c);
}
const protoEnd = new Date();
// using for and push
const pushStart = new Date();
for (let i = 0; i < b.length; i += 1) {
y.push(b[i]);
}
const pushEnd = new Date();
// using for and push
const batchPushStart = new Date();
for (let i = 0; i < b.length; i += 8) {
y.push(b[i]);
y.push(b[i + 1]);
y.push(b[i + 2]);
y.push(b[i + 3]);
y.push(b[i + 4]);
y.push(b[i + 5]);
y.push(b[i + 6]);
y.push(b[i + 7]);
}
const batchPushEnd = new Date();
// using forEach and push
const forEachStart = new Date();
b.forEach(i => z.push(i));
const forEachEnd = new Date();
console.log("Slice method:", sliceEnd - sliceStart);
console.log("Apply method:", protoEnd - protoStart);
console.log("For and push method:", pushEnd - pushStart);
console.log("For and batch push method:", batchPushEnd - batchPushStart);
console.log("Foreach and push method:", forEachEnd - forEachStart);
Run with 10,000,000 elements results on a 2014 MacBook Pro 15":
Slice method: 1400
Apply method: 275
For and push method: 896
For and batch push method: 409
Foreach and push method: 707
The for and foreach single-push methods are roughly equivalent in terms of performance on Chrome's V8. The slice method I'm seeing around 2-3x worse performance on.
Update: After adding the a batching method for Array.prototype.push.apply
it gives even better performance than the single-push methods! Unrolling the loop however seems to sometimes have a significant performance improvement and sometimes not, depending on the size of the list and other work being before or after it...?
Note that increasing the size of the initial x
array can crash the page in chrome because it can exceed the max memory limit for a page/tab.
To summarize, stick with a regular array.push(..)
for simplicity, but the batched Array.prototype.push.apply
method might be of interest for performance.