The internal heuristics are complicated, but the short story is that both
array.push(x) and array[array.length] = x should be very fast. What you're
doing seems unnecessary and potentially even bad for performance (if it
happens to defeat internal optimizations). Then again without measuring,
chances are this is premature optimization anyway and doesn't affect
overall performance of your app.
The only case where hand-tuning can be useful is when you know in advance
how big your array needs to be. In that case, initializing it to the proper
size is a good idea, e.g. ... = new Array(1024). Otherwise, I'd suggest to
simply let V8 do its thing. Feel free to file a bug if you encounter
something that's unreasonably slow.
Let's measure the actual performance:
function array_push(a, add) {
for (var i = 0; i < add.length; i++) {
a.push(add[i]);
}
}
function array_length(a, add) {
for (var i = 0; i < add.length; i++) {
a[a.length] = add[i];
}
}
function manual_growth(a, add) { // Your hand-"optimized" version.
var numElements = a.length;
if(add.length + numElements > a.length) {
a.length = add.length + numElements;
}
for(var i = 0; i < add.length; i++) {
a[numElements++] = add[i];
}
}
function pre_allocated(a, add, current_index) {
for (var i = 0; i < add.length; i++) {
a[current_index++] = add[i];
}
}
var N = 10000;
var M = 1000;
var push_time = 0;
var length_time = 0;
var growth_time = 0;
var pre_time = 0;
for (var j = 0; j < M; j++) {
var add = [1, 2, 3, 4];
var a1 = new Array();
var a2 = new Array();
var a3 = new Array();
var a4 = new Array(N * add.length);
var t1 = Date.now();
for (var i = 0; i < N; i++) array_push(a1, add);
var t2 = Date.now();
for (var i = 0; i < N; i++) array_length(a2, add);
var t3 = Date.now();
for (var i = 0; i < N; i++) manual_growth(a3, add);
var t4 = Date.now();
for (var i = 0; i < N; i++) pre_allocated(a4, add, i*add.length);
var t5 = Date.now();
push_time += t2 - t1;
length_time += t3 - t2;
growth_time += t4 - t3;
pre_time += t5 - t4;
}
print("Array.push: " + push_time + " ms.");
print("Array[length]: " + length_time + " ms.");
print("length = bigger: " + growth_time + " ms.");
print("pre-allocate: " + pre_time + " ms.");
$ out/ia32.release/d8 scratch.js
Array.push: 553 ms.
Array[length]: 543 ms.
length = bigger: 3022 ms. // Well...
pre-allocate: 434 ms. // This helps, but not much.
Takes these results with a grain of salt, though, like any microbenchmark.
array_push() and array_length() should have identical performance in most
cases (the difference above is flakiness); however we know about a few
situations where optimizations for one or the other will fail, and have
plans to fix those. Also, the relative performance of these three (and
other) implementations changes depending on the sizes of the arrays in
question and other characteristics of your app. So if you believe that this
is an actual performance bottleneck for you, you should measure yourself
whether that's actually the case (with the full app, not as a reduced micro
test!), and which implementation gives you the best performance.
On Wed, Dec 17, 2014 at 9:42 AM, Arthur Shefer <[email protected]> wrote:
> Heya,
>
> I'm developing a small compiler for JavaScript and wondering if someone
> could point out which is the most efficient way to handle array memory in
> V8. Currently, if array needs regular push/pops I will manually extend
> length and store numElements in additional variable (some what similar how
> std::vector works internally), like:
>
>
>
>
>
>
> *var array = new Array(2);var numElements = 0;var add = [ 1, 2, 3,
> 4]if(add.length + numElements > array.length) { array.length =
> **add.length
> + numElements**; *
> *}*
>
> *for(var i = 0; i < add.length; i++) {*
> * array[numElements++] = add[i];*
> *}*
>
> Or this is handled internally and i'm doing additional work?
>
> If i'm - does creating an array with capacity of 100000 and then resize it
> to only 1000 capacity will this create hidden "semi-memory leak"?
> If it will not, how V8 determines when to change capacity of an array
> internally?
>
> Thanks
>
> --
> --
> v8-users mailing list
> [email protected]
> http://groups.google.com/group/v8-users
> ---
> You received this message because you are subscribed to the Google Groups
> "v8-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>
--
--
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to the Google Groups
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.