Warty
Warty

Reputation: 7395

Local Variables take 7x longer to access than global variables?

I was trying to benchmark the gain/loss of "caching" math.floor, in hopes that I could make calls faster.

Here was the test:

<html>
<head>
<script>
window.onload = function()
{
  var startTime = new Date().getTime();
  var k = 0;
  for(var i = 0; i < 1000000; i++) k += Math.floor(9.99);
  var mathFloorTime = new Date().getTime() - startTime;

  startTime = new Date().getTime();
  window.mfloor = Math.floor;
  k = 0;
  for(var i = 0; i < 1000000; i++) k += window.mfloor(9.99);
  var globalFloorTime = new Date().getTime() - startTime;

  startTime = new Date().getTime();
  var mfloor = Math.floor;
  k = 0;
  for(var i = 0; i < 1000000; i++) k += mfloor(9.99);
  var localFloorTime = new Date().getTime() - startTime;

  document.getElementById("MathResult").innerHTML = mathFloorTime;
  document.getElementById("globalResult").innerHTML = globalFloorTime;
  document.getElementById("localResult").innerHTML = localFloorTime;
};
</script>
</head>
<body>
Math.floor: <span id="MathResult"></span>ms <br />
var mathfloor: <span id="globalResult"></span>ms <br />
window.mathfloor: <span id="localResult"></span>ms <br />
</body>
</html>

My results from the test:

[Chromium 5.0.308.0]:  
Math.floor: 49ms  
var mathfloor: 271ms  
window.mathfloor: 40ms  

[IE 8.0.6001.18702]  
Math.floor: 703ms  
var mathfloor: 9890ms  [LOL!]  
window.mathfloor: 375ms   

[Firefox [Minefield] 3.7a4pre]
Math.floor: 42ms  
var mathfloor: 2257ms  
window.mathfloor: 60ms   

[Safari 4.0.4[531.21.10] ]
Math.floor: 92ms 
var mathfloor: 289ms 
window.mathfloor: 90ms 

[Opera 10.10 build 1893]
Math.floor: 500ms 
var mathfloor: 843ms 
window.mathfloor: 360ms

[Konqueror 4.3.90 [KDE 4.3.90 [KDE 4.4 RC1]]]
Math.floor: 453ms 
var mathfloor: 563ms 
window.mathfloor: 312ms 

The variance is random, of course, but for the most part

In all cases [this shows time taken]:
[takes longer] mathfloor > Math.floor > window.mathfloor [is faster]

Why is this? In my projects i've been using var mfloor = Math.floor, and according to my not-so-amazing benchmarks, my efforts to "optimize" actually slowed down the script by ALOT...

Is there any other way to make my code more "efficient"...? I'm at the stage where i basically need to optimize, so no, this isn't "premature optimization"...

Upvotes: 6

Views: 427

Answers (3)

David Murdoch
David Murdoch

Reputation: 89312

I'm not sure why your benchmarks do what they do.

But if you are going to call Math.floor often you can use this:

var num = 9.99;
var floored = ~~num; // 9

Not that ~~ will probably fail on strings (var num = "9.99"), numbers out of the 32 bit range, and negative numbers (~~ will round up).

See this question for a little more information.


UPDATE
Here is an modified benchmark

On Chrome i'm getting the local scope returning faster than Math.floor and the global scope. (window.mfloor) Note that I'm not referencing the global mfloor with the window. syntax as in the original benchmark.

So, I think your test has 2 issues (besides the variable name mix up mentioned in other answers). One being that you were running the loop on window.mfloor and the other being that you had a local variable with the same name as a global variable (this is just speculation).

Try the benchmark using the jsbin link i posted and get back to me.


here is my benchmark for the lazy:

window.onload = function(){

  var k = 0, i=0, n = 2000000,
  startTime = +(new Date);
  for(; i < n; ++i) k += Math.floor(9.99);
  var mathFloorTime = (new Date) - startTime;

  window.globalMfloor = Math.floor;
  k = i = 0;
  startTime = +(new Date);
  for(; i < n; ++i) k += globalMfloor(9.99);
  var globalFloorTime = (new Date) - startTime;

  var mfloor = Math.floor;
  k = i = 0;
  startTime = +(new Date);
  for(; i < n; ++i) k += mfloor(9.99);
  var localFloorTime = (new Date) - startTime;

  alert("Math.floor: " + mathFloorTime);
  alert("globalMfloor: " + globalFloorTime);
  alert("mfloor: " + localFloorTime);
};​

Upvotes: 0

Joey Adams
Joey Adams

Reputation: 43380

Edit: Oops, I didn't read the answer about the field name mixup. It turns out that, in Firefox, accessing a local variable was faster (took 80% as long) as accessing Math.floor, but accessing a global variable took 140% as long.

In my original answer, I postulated that local variables are harder to access than global ones because of closure processing and whatnot. However, it seems to be the other way around.

Upvotes: 0

wombleton
wombleton

Reputation: 8376

You have these two variables labelled incorrectly:

var mathfloor: <span id="globalResult"></span>ms <br />
window.mathfloor: <span id="localResult"></span>ms <br />

@David's alternatives are worth looking into, as would some kind of memoisation.

Upvotes: 2

Related Questions