2013-07-09 11 views
7

Questo è, in un modo, un seguito al mio previous question.Loop Javascript eccezionalmente lento

ho creato a jsPerf che confronta un numero di modi per prendere una matrice 1-dimensionale RGB valori di pixel

var rgb = [R, G, B, R, G, B...] 

e convertire quelli in RGBA valori per una tela HTML5 (in cui il canale alfa è sempre 255, completamente opaco).

var rgba = [R, G, B, 255, R, G, B, 255...] 

Nel mio test, ho scoperto che una delle anse che ho provato, dal titolo "Per Loop", è astronomicamente più lento rispetto agli altri loop. Dove altri loop stavano completando l'operazione centinaia di milioni di volte al secondo, pesava a un enorme 86 volte al secondo. Il loop può essere trovato nel link jsPerf qui sopra, ma qui c'è un po 'di codice con "For Loop" e "4 * srotolato, salta alpha", uno dei loop più veloci nel test.

//Setup for each test 
function newFilledArray(length, val) { 
    var array = Array(length); 
    for (var i = 0; i < length; i++) { 
     array[i] = val; 
    } 
    return array; 
} 

var w = 160; //width 
var h = 144; //height 

var n = 4 * w * h; //number of length of RGBA arrays 
var s = 0, d = 0; //s is the source array index, d is the destination array index 

var rgba_filled = newFilledArray(w*h*4, 255); //an RGBA array to be written to a canvas, prefilled with 255's (so writing to the alpha channel can be skipped 
var rgb = newFilledArray(w*h*3, 128); //our source RGB array (from an emulator's internal framebuffer) 

//4*unrolled, skip alpha - loop completes (exits) 185,693,068 times per second 
while (d < n) { 
    rgba_filled[d++] = rgb[s++]; 
    rgba_filled[d++] = rgb[s++]; 
    rgba_filled[d++] = rgb[s++]; 
    d++; 
} 

//For Loop - loop completes (exits) 85.87 times per second 
for (var d = 0; d < n; ++d) { 
    rgba_filled[d++] = rgb[s++]; 
    rgba_filled[d++] = rgb[s++]; 
    rgba_filled[d++] = rgb[s++]; 
} 

Come può essere così incredibilmente simile nella sintassi, eppure è così lontano in termini di prestazioni?

+0

hai provato a cambiare l'ordine dei loop – aaronman

+0

Hai provato a utilizzare ['dis()'] (https://developer.mozilla.org/en-US/docs/SpiderMonkey/Introduction_to_the_JavaScript_shell#dis.28.5Bfunction. 5D.29)? –

+1

@aaronman Cosa intendi? jsperf esegue ogni test in un nuovo ambiente JS. – Barmar

risposta

10

Il motivo per cui solo il ciclo for è così lento è perché è l'unico caso di test corretto; tutti gli altri casi di test mai azzeramento, tra gli altri, il valore di d, quindi la prima iterazione è normale e il resto è ovviamente super veloce :)

Questo jsperf dà un risultato migliore, per cui il ciclo for è solo leggermente più lento del risultato più veloce.

Aggiornamento

Come bfavaretto suggerito, si dovrebbe anche reimpostare s e matrice di destinazione che si sta costruendo per un risultato più consistente. I suoi risultati possono essere trovati here.

+2

Penso che stava assumendo che il codice di preparazione è stato rieseguito prima di ogni iterazione del test. – Barmar

+0

@Barmar Questa sarebbe la mia ipotesi :) –

+0

Buona cattura! Ciò che mi ha confuso è che l'installazione afferma che "gira prima di ogni ciclo di test con clock, al di fuori della regione del codice temporizzato". Quella formulazione ancora ha fatto sembrare che l'installazione dovrebbe funzionare come pensavo sarebbe! –

Problemi correlati