2010-04-20 14 views
6

J'essayais de comparer le gain/la perte de «cache» math.floor, dans l'espoir que je pourrais faire des appels plus rapidement.Les variables locales prennent 7x plus de temps pour accéder que les variables globales?

Voici était le 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> 

Mes résultats de l'essai:

[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 

La variance est aléatoire, bien sûr, mais pour la plupart

Dans tous les cas [ cela montre le temps pris]:
[prend plus de temps] mathfloor> Math.floor> window.mathfloor [est plus rapide]

Pourquoi est-ce? Dans mes projets, j'ai utilisé var mfloor = Math.floor, et selon mes benchmarks pas si étonnants, mes efforts pour "optimiser" ralenti réellement le script par ALOT ...

Y at-il une autre façon de faire mon code plus efficace"...? Je suis à l'étape où j'ai fondamentalement besoin d'optimiser, donc non, ce n'est pas "l'optimisation prématurée" ...

+0

Je suis peut-être en train de lire ce qui ne va pas, mais vos étiquettes de texte ont l'air de faire référence à de mauvaises choses. On dirait qu'ils devraient être: Math.floor: ms
window.mathfloor: ms
var mathfloor: ms
Joe

Répondre

2

Vous avez ces deux variables étiquetés correctement:

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

@ alternatives de David sont dignes d'intérêt, comme le ferait une sorte de memoisation.

+0

Je me sens stupide maintenant. Je vous remercie. Pourriez-vous expliquer pourquoi Window.mathfloor prend une éternité mais Window.Math.floor ne le fait pas? – Warty

+1

Je suppose que c'est parce que les globals sont privilégiés dans leur recherche sur l'objet window; vous pouvez optimiser pour eux. Cette page http://www.webreference.com/programming/javascript/jkm3/ confirme vos conclusions et suggère que c'est parce que l'objet fenêtre est bondé dans le meilleur des cas. – wombleton

0

Je ne sais pas pourquoi vos benchmarks font ce qu'ils font.

Mais si vous allez appeler Math.floor vous pouvez souvent utiliser:

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

Non que ~~ échoueront probablement sur les chaînes (var num = "9.99"), le nombre de la gamme 32 bits et les nombres négatifs (~~ sera arrondi). Pour plus d'informations, reportez-vous à this question


MISE À JOUR
Voici un modified benchmark

On Chrome que je reçois la portée locale de retour plus vite que Math.floor et la portée globale. (window.mfloor) Notez que je ne référence pas le mfloor global avec la syntaxe window. comme dans le benchmark original. Donc, je pense que votre test a 2 problèmes (à part le nom de variable mélangé mentionné dans d'autres réponses). L'un étant que vous exécutiez la boucle sur window.mfloor et l'autre étant que vous aviez une variable locale avec le même nom qu'une variable globale (c'est juste de la spéculation). Essayez le benchmark en utilisant le lien jsbin que j'ai posté et revenez me voir.


voici mon point de repère pour les paresseux:

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); 
};​ 
+0

Ma question visait à être plus générale. Comme dans: pourquoi l'accès aux variables locales prend-il une éternité =/Math.floor n'était qu'un exemple. Thomas Fuchs a présenté la chose dans l'une de ses conférences d'optimisation, et oui, cela réduit le temps, mais ce n'est pas ce que je demande – Warty

+0

ok, je voulais juste le mentionner au cas où. Je suis curieux de connaître votre question et je fais des repères par moi-même. Je mettrai à jour ma réponse si je trouve quelque chose d'intéressant. –

0

Édition: Oups, je n'ai pas lu la réponse à propos du mélange des noms de champs. Il s'avère que, dans Firefox, accéder à une variable locale était plus rapide (80% plus long) qu'accéder à Math.floor, mais accéder à une variable globale prenait 140% de temps.

Dans ma réponse originale, j'ai postulé que les variables locales sont plus difficiles d'accès que les variables globales à cause du traitement de fermeture et autres joyeusetés. Cependant, il semble que ce soit l'inverse.

+0

Les variables locales de fonction sont recherchées avant les variables globales. – wombleton