ugrás a tartalomhoz

ECMAScript 5 strict mód és a teljesítmény

presidento · 2010. Szep. 22. (Sze), 18.11

Az ECMAScript 5-ben létrejött strict mód két céllal rendelkezik meglátásom szerint: egyrészt a rossz programozási technikák és véletlen elgépelések ellen véd (lásd: minden változót deklarálni kell, a this nem lesz automatikusan global scope), másrészt a teljesítményre van jó kihatással. Jelen bejegyzésben az utóbbit szeretném megvizsgálni a jelenleg elérhető strict módot támogató JavaScript motorok vizsgálatával.

A Web Reflections felhevülten írja az [ECMAScript 5] Do Not Remove arguments.callee! bejegyzésébén 2009 májusában (kiemelések az eredeti cikk szerint):

Introspection and BackTrace? They Decided It Is A Bad Thing!

Without arguments.callee we are loosing arguments.callee.caller as well, often the only way we have to truly debug our code. At the same time the dynamic nature of JavaScript where "you can inject whatever wherever" will loose a big portion of its malleability.

Everything For Performances Reason ???

Apparently what this "new" language would like to get rid off is arguments variable, probably the most used variable ever, the inspiration of every ArrayLike object or library. This would be for performances, where we need as first step to call 2 functions rather than one for each runtime function assignment (setTimeout example and every assigned inline lambda) and where everybody will try to overload the language itself providing other methods to emulate the good old stuff!

[…]

Have fun with ECMAScript 5 and its brilliant strict mode.

Az Updating JavaScript: ES5 előadás (Where's Walden) 11. fóliáján (Strict Mode Effects) pedig ez áll:

No stack introspection via caller/callee/fun.arguments (modern JIT engines cry)

Jelenleg egyetlen JavaScript motor van a világon, ami teljes körűen támogatja a strict módot, ez pedig a BESEN. A honlapja szerint:

Strict code runs faster than non-strict code, for that reason please use preferably "use strict" where is it possible, because at strict code is the arguments object creation cheaper at funtion calls, for example no setter/getter creation for each function argument in the arguments object.

A Minefieldnek (Firefox 4 kódneve) már csak négy pontot kell teljesítenie a teljes strict mód támogatásához: a thisből ne legyen global scope (3 pont), és parseInt('08') === 8 (1 pont): mily' öröm, a teljesítménnyel összefüggő részeket már implementálták.

Nézzük, mit mutatnak a száraz tények. Teszt scriptem a Web Worker-ekről szóló cikkben megismert prímszám kereső (azzal a különbséggel, hogy itt azt mérjük, időegység alatt mennyi prímet találtunk).

//"use strict";
function isPrime(num) {
	//arguments; // (1)
	//arguments.callee; // (2)
	//arguments.caller; // (3)
	//isPrime.caller; // (4)
	//isPrime.arguments; // (5)

	for (var i = 2; i <= Math.sqrt(num); i++ ) {
		if (num % i == 0) {
			return false;
		}
	}
        return true;
}

var num = 123456789, count = 0, start = new Date();

while ( +Date.now() - start < 2000 ) {
	if (isPrime(++num)) {
		++count;
	}
}

alert( count );

Először lefuttatom strict módban, majd strict mód és arguments elérés, ezután következik a normál mód, ami közben mindig csak egy sort engedélyezek az (1) - (5) közül. Íme, az eredmények (időegység alatt elvégzett számítások száma, a nagyobb a gyorsabb):

Minefield

BESEN

Ami ebből látszik, az leginkább az, hogy Minefield esetén teljesítmény szempontjából mindegy, hogy strict vagy normál módban fut a program (ha strict mód kompatibilisan van megírva), a BESEN-nél pedig közel mindegy. (Itt normál módban az argumentsre való hivatkozáskor az egész objektumot létrehozza, ezért tud egy kicsivel gyorsabb lenni a strict mód.)

Az idő majd megmutatja, megérte-e a szabványban rögzíteni ezen, valóban költséges attribútumok hiányát, jelenleg és a közeljövőben talán a legcélszerűbb strict módban kódolni, és normál módban végezni a hibakeresést/futtatást.

Mi a véleményetek?

Utóirat: a cikk megjelenése után Benjamin „BeRo” Rosseaux (a BESEN fejlesztője) felvette velem a kapcsolatot és egy nagyon hasznos tanáccsal látott el: ha az aktuális dátumot szeretném elérni, a +new Date() helyett használjam a +Date.now() kifejezést, mert az előbbi esetén minden meghíváskor a garbage collector-nak is dolgoznia kell. És valóban, az új kóddal a 25 000-es értékről rögtön 125 000 fölé emelkedett a BESEN strict mód-beli teljesítménye. (A Minefield alatt is javult az érték kb. 320 ezerről 370 ezerre.) Azonban a kontraszt még kisebb lett a strict módban futó és a strict-kompatibilis, de normál módban futó program között.

 
1

Benjamin Rosseaux szerint

presidento · 2010. Szep. 23. (Cs), 10.06
The strict mode allows simply better bytecode and JIT codegen optimizations at the engine side, when the non-strict mode stuff will stripped completely out in someone future ECMAScript spec. version. For example the arguments object or the WITH statement are really nightmares for ECMAscript engine implementors (like me) for the bytecode code execution performance + JIT native code generation.

Non-strict and strict modes are mostly equal fast in the moment, because the strict-mode codepaths contains mostly still some dummy non-strict-mode stuff, and on the other side, many engines incl. BESEN optimizes the argument object even in the non-strict-mode out (for the function code context creation), if it's not used, so that the performance advantage for to the strict mode will be here very fully minimal in the moment.
2

Hasznos a strict-mode, de ez

ironwill · 2010. Szep. 23. (Cs), 12.21
Hasznos a strict-mode, de ez is akkor fog működni, ha a böngszőkészítők implementálni, a fejlesztők alkalmazni fogják.

Lehet, hogy sokan fognak ezzel vitatkozni, de: a strict-mode útja nagyban függ a framework fejlesztőktől. Egyre többen használnak keretrendszereket a natív js mellett || helyett (elég csak a JQuery, Prototype, Scriptaculous, Mootools, ExtJS stb. népszerűségére gondolni).
3

ugyan…

presidento · 2010. Szep. 23. (Cs), 12.35
John Resig (a jQuery fejlesztője) azt írja 2009. májusában (kiemelés tőlem):
All that being said, I'm fairly certain that jQuery is ES5-Strict compatible right now. Once an implementation of the language is made available (so that that premise may be tested) I'll happily switch jQuery over to working exclusively in strict mode.


Pedig onnantól még hét hónap kellett, hogy kiadják a szabványt, és több, mint egy év, hogy megjelenjen az első implementáció.
4

jquery.. és a többiek?

ironwill · 2010. Szep. 23. (Cs), 15.10
A JQuery csak egy framework.
És nem kijelentettem, hogy a keretrendszerek nem fogják támogatni.

a strict-mode útja nagyban függ a framework fejlesztőktől


Ezzel azt mondtam, hogy mivel már elég jelentős befolyása van a különböző keretrendszereknek, ezért az azokat fejlesztők, indirekt módon befolyásolják a keretrendszer (fel)használókat a strict-mode használatában.
5

Széljegyzet

Török Gábor · 2010. Szep. 23. (Cs), 20.52
Teljesen mellékes, de milyen megfontolásból van megjegyzésben a "use strict"; jelölés? Ez a javasolt minta?
6

Nem mellékes

presidento · 2010. Szep. 23. (Cs), 21.46
Nagyon jó a kérdés, egyáltalán nem mellékes: a teszteket úgy futtatam le, hogy az éppen aktuális sorok elől kivettem a megjegyzést: A program akkor van strict módban, ha ez a sor nem comment.

Az ECMAScript 5 szabvány 14.1 pontja (111. oldal) szerint az egész JavaScript kód vagy egy függvény legelső utasítása lehet úgynevezett utasítás prológus (Directive Prologue – mi ennek a magyar megfelelője?), ami egy string literal pontosvesszővel lezárva (ez lehet automatikus beszúrással). Ennek megfelelően az Use Strict direktíva a következő kettő valamelyikével pontosan meg kell, hogy egyezzen: 'use strict' vagy "use strict".
7

Oké

Török Gábor · 2010. Szep. 23. (Cs), 21.53
Én is így gondoltam, csak félreértettem a jelölésed, de így világos. Kösz!
8

Csak egy észrevétel

haasz · 2010. Szep. 30. (Cs), 16.54
Szerintem a fenti kódban a második return utasításnak egy blokkal kijjebb kellene szerepelni, mert így a for ciklus magja minden függvényhíváskor csak egyszer fut le. Például az isPrime(9) is true értékkel tér vissza, ami persze nem igaz.
9

Javítottam, kösz az

Török Gábor · 2011. Feb. 23. (Sze), 17.46
Javítottam, kösz az észrevételt.