Reputation: 12666
I have a value stored as a string, and I know it will always be a whole number. But I need it as a number, so I was doing n = n * 1
. Then I thought "hmm, I should probably just use parseInt()
. Then I ran some jsperf tests, and the results in Firefox were interesting:
Across the board, it appears the operations are pretty similar, except in Firefox, using *1
is exceptionally faster. What's going on here?
Edit
Someone made the base 10 test, and updated the tests overall. Click away on this one too to give some extra feedback: http://jsperf.com/parseintx1/2
Upvotes: 15
Views: 2284
Reputation: 122888
It has to be the test setup, since this version gives the expected result in Firefox too. The thing, in your setup I think, is that parseInt
is applied (well, in FF at least) in every iteration to every variable, whereas the conversion from String
to Number
may be applied the first iteration in the multiplication test, after which the variables are numeric and multiplication needs no conversion anymore.
In version 7 the variables are assigned in the test setup, and the test assigns new variables at every iteration. Now both tests have 'equal changes', and parseInt
outperforms the multiplication test.
After inspecting the test in IE[8,9] and seeing its results look like those of FF I think there's an explanation for the Chrome results: I'm pretty sure Chrome/Webkit has a better optimization in the first version of the test (especially the parseInt
part), which gives a better result for parseInt
there. It may be the precompilation of (parts of) the code in the V8 engine, used in those browsers.
Upvotes: 2
Reputation: 413682
I'm not a JavaScript engine expert by any means, or even a compiler expert, but I'm pretty sure that it boils down to the fact that the compiler can tell that this:
var a = "123";
a = a * 1;
is really exactly the same as:
var a = 123;
Because "a" is a local variable, and is unused from the point of its initialization to that * 1
expression, there's no point generating code to carry out the operation at all. After that point, the compiler may also be able to tell that there's no way that "a" can "escape" from the function, so there's really no point doing anything; that is, it may be that the * 1
test ends up with something equivalent to what you'd get from:
function() {}
In the parseInt()
case, however, the compiler can't be sure that parseInt()
is really parseInt()
, as it may have been redefined. Thus, it has to generate code to make the function call.
Upvotes: 2