Sunday 7 February 2010

Godbiten Javascript

Javascript er et fantastisk herlig programmeringsspråk.

Her er grunnene til at jeg liker javascript:
- Ingen klasser! Alt er objekter.
- Dynamisk tolket språk som ikke er strengt typet, full fleksibilitet mht utvidelse.
- Intet behov for generics eller innviklede mønstre for å oppnå det javascript
greier på en elegant måte.
- Det programmeringsspråket i verden flest mennesker har tilgang til, nemlig som
en tolker i en nettleser.
- Innebygd støtte for lambda-uttrykk og avansert funksjonalitet som Javascript har
arvet fra Scheme.
- Det herligste, mest elegante språket i verden!

Jeg håper Ecmascript 5 ikke lager en stor bloatware ut av Javascript, men at språket
sin nette eleganse og enkelhet bevares som i dag. Det er nettopp enkelheten og
fleksibiliteten som gjør Javascript så kraftig.

Jeg anbefaler å se videoene av Douglas Crockford på Yahoo! sin video side.

Spesielt følgende video anbefales!

JavaScript: The Good Parts.

Javascript har selvsagt sine "flaws" også og Douglas Crockford går gjennom disse på en hysterisk morsom måte. (Man må være innvidd i denne bransjen for å sette pris på slike ting da..).

Mvh Tore A

Raskere Javascript med document-fragments?

Jeg har undersøkt litt om man får kjøre raskere Javascript vha. document-fragments. Sentralt i denne teknikken er å benytte document.createDocumentFragment(). Dette er en "construct" eller byggekloss som tillater en å klargjøre store modifikasjoner i HTML DOM treet i en operasjon. Dermed slipper man "reflow", dvs. at nettleseren forsøker å tegne opp html dom treet, hver gang man setter inn et nytt element.

Jeg har testet teknikken ved å lage en Javascript kode som regner ut tiden det tar i antall millisekunder å sette inn 1000 elementer i et HTML nedtrekksliste, etter først å ha slettet 1000 elementer, hvis nødvendig, i samme nedtrekksliste. Enten ved å bruke document-fragments, eller ved å direkte manipulere HTML dom treet for hver iterasjon. Resultatene viser seg at effekten er mindre enn mange andre tester har vist, men det er størst effekt i Internet Explorer. IE er helt klart også den nettleseren med dårligst Javascript-ytelse for akkurat dette.

Resultatene ble som følger (målt i antall millisekunder, mindre er bedre=raskere!):
With Fragment Without Fragment
IE 8.0 608 1070
Firefox 3.6 77 100
Safari 4.0 69 74
Opera 10.5 77 76
Chrome 4.0 87 92

Resultatene er etter kjøring av Javascript som setter inn 1000 elementer og sletter hvis nødvendig de 1000 elementene først og hvert case er kjørt 10 ganger og tatt gjennomsnitt av. IE 8.0 er nesten dobbelt så rask med document-fragment teknikken som uten. Likevel er IE 8.0 i sin egen liga i å være tregere enn de andre nettleserne. Som man ser av tallene over er Safari 4.0 9x-10x raskere med fragment teknikken. Safari 4.0 er mer enn 12x raskere enn IE 8.0 uten fragment teknikken. Safari er forøvrig den raskeste browseren, både med og uten document-fragment. Opera, Safari og Chrome viser små hastighetendringer med document-fragment. Opera 10.5 er faktisk litt raskere uten.. Chrome og Safari har små bedringer, ca. 5-10% raskere. Etter Safari er Opera raskest, Chrome og Firefox er ganske jevne. Chrome er tregere enn Firefox med document-fragment, men kjøringen uten document-fragment viser at Chrome er raskere enn Firefox 3.6. Firefox har ca. 30% raskere utførelse med document-fragment.

Konklusjonen må derfor være at document-fragment må absolutt brukes. IE 8.0 er meget treg i sin Javascript-ytelse og doblingen i hastighet (100% raskere) er nødvendig å utføre. Er du opptatt av hastigheten til webapplikasjonene dine i IE 8.0 er document-fragment meget viktig å bemerke seg med andre ord. For de andre nettleserne er det Firefox 3.6som er mest følsom for document-fragment, med 30% raskere utførelse. De andre browserne har 10-5% økning i raskere utførelse, men for dette caset hadde Opera 10.5 Alpha -1 til -5% økning i hastighet.. Safari er forøvrig den aller raskeste nettleseren. Det at Safari 4.0 skal med en slik enkel test med HTML DOM manipulasjon i javascript være mellom 9x-12x raskere enn IE 8.0: Dette er for dårlig Microsoft! Hvis IE 9 skal bli tatt seriøst som en nettleser og tatt i betraktning Microsoft sine enorme finansielle muskler, må de seriøst fikse Javascript hastigheten sin. Er du på utkikk etter den aller raskeste browseren gir denne testen en klar indikasjon på at JS-ytelsen i Safari er best. Opera og Chrome er hakk i hæl, Firefox sist av disse fire, men langt foran IE 8.0. Det skal nevnes at Opera 10.5 Alpha er en Alpha-versjon og kanskje kan nå opp til Safari 4.0.4 sine høyder i nær framtid..

Jeg har i Google Docs Spreadsheet laget et diagram på ytelsen:



Legg merke til den dramatisk raskere utførelsen i IE 8.0 med document-fragment. Ikke alle nettlesere har spesiell stor ytelsesforbedring, ca. 5-30%, med Firefox som den nettleseren som nyter best av å benytte document-fragment.

Her er testen vist under kjøring i Google Chrome 4.0:



Jeg vil nå oppsummere resultatene fra denne testen:
- Kjører man IE 8.0 må nesten document.createDocumentFragment() benyttes når store
HTML DOM manipulasjoner kjører i nettleseren, pga IE 8.0 sin dårlige hastighet.
- IE 8.0 er 9x-12x tregere enn Safari 4.0.4 i JS-ytelse. Dette er ikke bra Microsoft..
- For de andre nettleserne er det også bra å bruke document.createDocumentFragment(), forbedringen er 5-30%, men Opera hadde ikke noen ytelsesforbedring..
- Generelt sett, benytt document-fragment likevel, evt. unngå det for Opera med
oppdaging av klientens nettleser..
- Testen viser at Safari 4.0.4. er aller raskest, Opera 10.5 og Chrome 4.0 er hakk i hæl. Firefox 3.6 er nest tregest, men milevis foran IE 8.0 i JS-ytelse.

For de som ønsker å teste ut selv, kan de laste ned en zippet versjon av løsningen som jeg laget i Visual Web Developer Express 2008 her:
Document Fragment Demo Test Solution.

For å teste gjør følgende:
1. Pakk ut .zip filen
2. Åpne .sln filen
3. Når Visual Studio er startet, trykk F5 for å starte.

Klikk på de to knappene for å kjøre tester med document-fragment i ulike nettlesere.

Da skulle vel Microsoft-utviklere der ute ha noen pekepinner om hvor skoen trykker i
JS-ytelse for neste versjon av IE 9.x! De øvrige nettleserne er mindre følsomme for document.createFragment() men man bør unngå reflow inne i iterasjoner i javascript, eller spesifisere det enklere på en måte som er optimert for hastighet. Problemet ligger her i at nettleseren ønsker å holde GUI-visuelt oppdatert hele tiden. I en iterasjon er ikke det nødvendigvis en god teknikk for en nettleser. Klienten vil jo helst ha innholdet sitt og starte å jobbe videre, nettlesere er jo som kjent single-threaded miljø når det kommer til GUI. Da bør nettlesere unngå reflow inne i iterasjonen og først starte med en reflow rett etter en slik for-loop slik at man slipper å gjøre rene hacks for å få nettleseren til å være rask og responsiv.

Jeg limer inn javascript-koden her til slutt:


///Runs a desired function, returns amount of millisecond the function took to perform before completing.
function timedFunction(func) {
if (typeof func == 'function') {
var startTime = (new Date()).getTime();
func();
var endTime = (new Date()).getTime();
return (endTime - startTime);
} //if
return 0;
}

function generate_thousand_option_elements_in_dropdown_with_document_fragment() {
var optionsFragment = document.createDocumentFragment();
var ddltest = document.getElementById("ddlTest");
var len = 0;
while (len = ddltest.options.length) {
ddltest.options[len-1] = null;
}
for (var i = 1; i <= 1000; i++) { var optiontoadd = document.createElement("option"); optiontoadd.value = i; optiontoadd.appendChild(document.createTextNode("Option " + i)); optionsFragment.appendChild(optiontoadd); } ddltest.appendChild(optionsFragment); } var withoutFragmentTest = 0; function generate_thousand_option_elements_in_dropdown_without_document_fragment() { withoutFragmentTest++; var ddltest = document.getElementById("ddlTest"); var len = 0; while (len = ddltest.options.length) { ddltest.options[len-1] = null; }
for (var i = 1; i <= 1000; i++) { var optiontoadd = document.createElement("option"); optiontoadd.value = i; optiontoadd.appendChild(document.createTextNode("Option " + i)); ddltest.appendChild(optiontoadd); } }generate_thousand_option_elements_in_dropdown_without_document_fragment var withFragmentTest = 0; function testDocumentFragment() { withFragmentTest++; var resultRun = timedFunction(generate_thousand_option_elements_in_dropdown_with_document_fragment); if (resultRun != 'undefined') { var resultParagraphNode = document.createElement("p"); var resultParagraphTextNode = document.createTextNode("Ran test #"+ withFragmentTest + " with document fragment. Test took: " + resultRun + " milliseconds."); resultParagraphNode.appendChild(resultParagraphTextNode); document.getElementById("resultList").appendChild(resultParagraphNode); } //if }
testDocumentFragment () function testWithoutDocumentFragment() { var resultRun = timedFunction(generate_thousand_option_elements_in_dropdown_without_document_fragment); if (resultRun != 'undefined') { var resultParagraphNode = document.createElement("p"); var resultParagraphTextNode = document.createTextNode("Ran test #" + withoutFragmentTest + " without document fragment. Test took: " + resultRun + " milliseconds."); resultParagraphNode.appendChild(resultParagraphTextNode); document.getElementById("resultList").appendChild(resultParagraphNode); } } testWithoutDocumentFragment




Mvh Tore Aurstad

Thursday 28 January 2010

Slider-kontroll på web


Jeg har testet ut Scriptaculous, som er et javascript bibliotek myntet på gui og effekter i gui. Det har blant annet en slider kontroll, som jeg har laget et testprosjekt for. Slideren ser meget elegant ut og er vel så god som den som
Silverlight kan tilby. Best av alt er at man har tilgang til HTML DOM-treet og lett kan lese ut og sette verdier til Slideren.

For å laste ned testprosjektet, last ned her [ZIP-fil,101kB].

Start prosjektet på følgende måte:
* Pakk ut Zip-filen TestSliderScriptaculous.zip i en midlertidig mappe.
* Åpne denne mappen og dobbeltklikk på .sln filen.
* Når Visual Studio er lastet (Jeg har anvendt Visual Web Developer 2008 Express):
* Trykk på F5 for å snurre film.
* Standard nettleser skal så åpne og man presenteres siden Default.aspx hvor jeg har
implementert testprosjektet.

Øverst i denne artikkelen ser du et skjermbilde hvordan slideren ser ut. Like elegant som den du ser i Mac OS X, eller hva? Slideren er selvsagt interaktiv. Klikk og dra på slider handelen (håndtaket) og slipp for å sette en verdi for slideren. For dette testprosjektet har jeg satt 0 og 100 som verdiintervallet og alle titallsverdier som diskrete verdier. Hvis man ikke setter noen verdier her vil man med slideren spesifisere en verdi mellom 0 og 1 som et flyttall.

Dette er en meget kraftig måte å presentere en slider på i web. Man benytte denne kontrollen i for eksempel en Ajax-aktivert Web 2.0. applikasjon, for eksempel for å sette en tallverdi, e.g. 0 til 100 prosent gjennomsiktighet i en bilde-applikasjon eller parametere inn til et filter i en bilde-applikasjon.

Script.aculo.us inneholder nok mange andre godbiter, jeg har ikke fått testet ut rammeverket noe mye enda. Sliderkontrollen var meget lett å få til å virke, det tok meg kun 2-3 timer å få ferdigstilt testprosjektet. Om noen kjenner andre gode demoer av Script.aculo.us, si i fra. Litt kjapt nettsøk viser at det er tonnevis av demoer der ute.

Dette testprosjektet inneholder Script.aculo.us i Script mappen, som er rett og slett noen få .js filer.

Script.aculo.us nettside (inkluderer nedlasting):