Solo per vedere come funziona, ho scritto a mano un modulo asm.js molto breve, che simula l'equazione delle onde 2D usando la matematica a 32 bit interi e gli array tipizzati (Int32Array). Ho tre versioni di esso, tutto il più possibile simili:Perché asm.js peggiora le prestazioni?
- ordinaria (cioè leggibile, anche se C-style) JavaScript
- Uguale a 1, con asm.js annotazioni aggiunte in modo che passi il validatore, in base a Firefox e altri strumenti
- Uguale a 2, tranne che con "usa asm"; direttiva nella parte superiore
Ho lasciato una demo al http://jsfiddle.net/jtiscione/xj0x0qk3/ che consente di passare da un modulo all'altro per vedere gli effetti dell'utilizzo di ciascuno. Tutti e tre funzionano, ma a velocità diverse. Questo è l'hotspot (con annotazioni asm.js):
for (i = 0; ~~i < ~~h; i = (1 + i)|0) {
for (j = 0; ~~j < ~~w; j = (1 + j)|0) {
if (~~i == 0) {
index = (1 + index) | 0;
continue;
}
if (~~(i + 1) == ~~h) {
index = (1 + index) | 0;
continue;
}
if (~~j == 0) {
index = (1 + index) | 0;
continue;
}
if (~~(j + 1) == ~~w) {
index = (1 + index) | 0;
continue;
}
uCen = signedHeap [((u0_offset + index) << 2) >> 2] | 0;
uNorth = signedHeap[((u0_offset + index - w) << 2) >> 2] | 0;
uSouth = signedHeap[((u0_offset + index + w) << 2) >> 2] | 0;
uWest = signedHeap [((u0_offset + index - 1) << 2) >> 2] | 0;
uEast = signedHeap [((u0_offset + index + 1) << 2) >> 2] | 0;
uxx = (((uWest + uEast) >> 1) - uCen) | 0;
uyy = (((uNorth + uSouth) >> 1) - uCen) | 0;
vel = signedHeap[((vel_offset + index) << 2) >> 2] | 0;
vel = vel + (uxx >> 1) | 0;
vel = applyCap(vel) | 0;
vel = vel + (uyy >> 1) | 0;
vel = applyCap(vel) | 0;
force = signedHeap[((force_offset + index) << 2) >> 2] | 0;
signedHeap[((u1_offset + index) << 2) >> 2] = applyCap(((applyCap((uCen + vel) | 0) | 0) + force) | 0) | 0;
force = force - (force >> forceDampingBitShift) | 0;
signedHeap[((force_offset + index) << 2) >> 2] = force;
vel = vel - (vel >> velocityDampingBitShift) | 0;
signedHeap[((vel_offset + index) << 2) >> 2] = vel;
index = (index + 1)|0;
}
}
La versione "normale JavaScript" è strutturato come sopra, ma senza gli operatori bit per bit che richiede asm.js (ad esempio "x | 0", "~ ~ x "," arr [(x < < 2) >> 2] ", ecc.)
Questi sono i risultati per tutti e tre i moduli sulla mia macchina, utilizzando Firefox (Developer Edition v. 41) e Chrome (versione 44), in millisecondi per iterazione:
- FIREFOX (versione 41): 20 ms, 35 ms, 60 ms.
- CHROME (versione 44): 25 ms, 150 ms, 75 ms.
Quindi il comune JavaScript vince in entrambi i browser. La presenza di annotazioni richieste da asm.js peggiora le prestazioni di un fattore 3 in entrambe. Inoltre, la presenza dell '"uso asm"; la direttiva ha un effetto ovvio: aiuta un po 'Firefox, e mette in ginocchio Chrome!
Sembra strano che la semplice aggiunta di operatori bit a bit dovrebbe introdurre un triplice degrado delle prestazioni che non può essere superato dicendo al browser di utilizzare asm.js. Inoltre, perché dire al browser di usare asm.js è di aiuto solo marginalmente in Firefox, e completamente ritorcersi contro Chrome?
Per iniziare, ho eseguito il benchmark ["Massive"] (https://kripken.github.io/Massive/) in Chrome 44 e FF 39 (Win XP, 32 bit), ecco i risultati per [Chrome ] (http://pastebin.com/fZQYzWKs) e [Firefox] (http://pastebin.com/brtZHecb) (copia e copia nel campo "inserisci i dati copiati da un'altra corsa" sulla pagina di benchmark - sì, funziona con l'HTML effettivo). Tranne che per un punto ("poppler-cold-preparation"), Chrome è stato più lento ovunque, nel caso più estremo 24,6 volte più lento di FF. Sembra che Chrome al momento non sia in grado di gestire asm.js in modo ragionevole. – Siguza
solo un'idea, hai "benchmark" le chiamate successive/ripetute, dato che asm userà più tempo durante le fasi di compilazione/opt (suppongo)? – birdspider
@birdspider Significa eseguire il benchmark più volte? No, ho appena preso quello che c'era ... l'interfaccia attuale sembra richiedere una ricarica della pagina per eseguire nuovamente il benchmark, molto probabilmente richiedendo nuovamente la compilazione/ottimizzazione del codice. Ma l'intero benchmark è durato circa 15 minuti per me, quindi penso che il tempo di compilazione non sia un granché. Se Chrome impiega così tanto tempo per essere compilato, mi sconcerta che il codice riesca addirittura a funzionare * affatto *. – Siguza