Scott said:
I was trying really hard not to get sucked into the navel-gazing
arguments so prevalent here. So much for my New Year's resolution, I
guess.
The test you created cannot be used as a premise to a conclusion of loop
direction speed.
Thomas offered a suggested improvement to my function. My tests show
that for most reasonable cases it was an improvement, and also that
it's not as clear-cut as he suggested.
Your tests do not show that a forwards loop is faster than a reverse
loop. They do not show that `push` is slower than [[Put]] (though that
should be obvious). The tests you provided prove nothing.
Think about `myArray.push()` versus `[[Put]]` with property accessors.
To call `myArray.push()`, the ECMAScript interpreter must resolve the
push property. The push property is not resolved on the object, it is
resolved on the object's prototype, Array.prototype. After `push` has
been resolved to a value, the interpreter calls it `myArray` for the
`this` value and an internal `ArgumentList` of the arguments passed.
Compare that to Array [[Put]].
In Array [[Put]](p, v), if `myArray` does not have a property with name
p, then it is created and given the value v.
If converting the property name to a numeric representation (ToUnit32)
is >= length, then 'myArray.length` is increased to `ToUnit32(p) + 1`.
I should have known better
than to distinguish one implementation from another on the basis of
one of their features (forward/backward), but I guess I'm stuck with
it now!
It is a misleading test.
If I find some time tonight or tomorrow, I'll do a few more thorough
benchmarks of multiple versions of the algorithms and see what the
main issues are.
The loop backwards using arrays seems to be slower then the loop forwards.
Results:
Opera 10.10:
forwards()
353
backwards()
432
Firefox 3.5.5:
forwards()
64
backwards()
933
Seamonkey
forwards()
1927
backwards()
2600
IE7:
forwards()
2141
backwards()
2502
Safari 4:
forwards()
66
backwards()
3458
Safari 3:
forwards()
1079
backwards()
8646
Safari 2:
(out of memory errors).
<!doctype html>
<html lang="en">
<head>
<title>loop test</title>
</head>
<body>
<script type="text/javascript">
var ITERATIONS = 1000000;
function forwards(){
var x = [], d = +new Date, noise = Math.PI,
i, len = ITERATIONS, time;
x.length = len;
for(i = 0; i < len; i++){
x
= i + noise;
}
time = new Date-d;
document.getElementById("f").innerHTML = String(time);
}
function backwards(){
var x = [], d = +new Date, noise = Math.PI,
len = ITERATIONS, time;
x.length = len;
for(i = len; i-- > 0{
x = i + noise;
}
time = new Date-d;
document.getElementById("b").innerHTML = String(time);
}
</script>
<button onclick="forwards();">forwards()</button>
<pre id="f">-</pre>
<button onclick="backwards();">backwards()</button>
<pre id="b">-</pre>
</body>
</html>
What is the explanation for Thomas' certainty that the backwards loop
would be faster? One possibility is irrational mentality. Another
possibility is that a backwards loop had been observed to be faster at
one point.
If a backwards loop had been observed to be faster, then it is worth
investigating the test that made such conclusion.
It is likely that that test did not set the `length` property of the
resulting array prior to looping. If that is the case, then the loop
forwards has a penalty of:
| 10. Change (or set) the value of the length property of A to
| ToUint32(P)+ 1.
Resetting the length on every iteration (implicitly, in step 10 of Array
[[Put]]), demands more work of the implementation.
The key to populating an array quickly is setting the length of the
array beforehand.
The direction of the loop should not be chosen based on speed, but by
the order desired of the resulting array.