En text-editor, del 4
Tidigare delar är skriven på Engelska: del 1:, del 2, del 3
För närvarande jobbar jag med att bygga ett text-"redigerings"-program, en så kallad "editor", som är specialiserad på JavaScript och närliggande programmerings-språk så som HTML, CSS, PHP och ASP. Den klarar även av att editera JSON och XML filer. Tanken är att jag ska implementera stöd för fler format i framtiden, men fokus kommer att ligga på JavaScript och webbutveckling.
Varför JavaScript?
För några år sedan upptäckte jag NodeJS vilket är en motor för
att köra generella program i JavaScript. JavaScript har tidigare endast används i webbläsaren för att
skapa interaktiva funktioner på hemsidor, men nu kan man använda JavaScript till allt!
Förutom att skapa vanliga hemsidor är det mycket, mycket enklare och snabbare att skapa program för
NodeJS jämfört med ASP och PHP. I NodeJS kan man till exempel skapa TCP/UDP sockets,
video-strömmar, och real-tids program, vilket ASP och PHP helt enkelt inte är byggt för.
Och när NodeJS klarar av allt som ASP, PHP och ISS/Apache gör, plus mycket mer, och dess utom bättre,
är det ingen ide att fortsätta med ASP/PHP.
- Vilket programmerings-språk använder jag för att skapa editorn?
- I vilket språk har jag gjort motorn för denna blog?
- I vilket språk är special-funktionerna på hemsidan, till exempel kommenterings-funktionen, skapad i?
- Vilket språk används på server-sidan för att ta emot och lagra kommentererna?
Svar: JavaScript!!
Kodanalys i realtid
Min editor analyserar koden allt eftersom man skriver. Den upptäcker buggar, indenterar koden automatiskt, och om du blandar html, JavaScript och ASP/PHP så förstår den vad som är vad. Du kan när som helst klicka på tab-tangenten och editorn skriver automatiskt in det den tror du tänker skriva!
Varje gång en tangent tryckts ner går editorn igenom all kod. Detta går förvånansvärt fort, så jag har hittills inte optimerat den funktionen. Men ju mer avancerad den blir, desto segare går det. Och denna vecka var det dags för optimering! Jag lyckades få ner editorns svars-tid i stora filer från 70ms till 2-3ms!
Användarupplevelse och lagg
Några exempel ...
- Video-filmer spelas upp med ca 25 bilder per sekund. Det är 40ms per bild.
- Den mänskliga reaktionstiden är ca 200ms.
- För att det inte ska räknas som tjuvstart, är minsta tillåtna reaktionstiden på 100m 100ms.
Allt under 20-30ms upplevs som "mjukt", omedelbart, och hack/lagg-fritt.
Moderna bild-skärmar visar 60 bilder per sekund, vilket är ca 16ms per bild. Om editorns svars-tid är under 16ms kommer bild-skärmen att uppdateras max 16-32ms efter att informationen skickats.
Optimering
Från början tog det totalt ca 70ms för editorn att hantera och analysera en tangent-nertryckning i en fil på över fyra tusen rader, vilket gjorde att det hackade/laggade.
- Uppdatera filen i minnet: 5ms
- Analysera filen 55ms
- Bygga lista med funktioner: 5ms
- Uppdatera grafiken: 5ms
Då nästan 80% av tiden gick åt till att analysera filen var det mest värt att optimera den funktionen.
Att optimera JavaScript är mycket speciellt, eftersom JavaScript motorn i sin tur optimerar koden, ju oftare den körs.
När jag körde funktionen 10ggr per sekund, som om det vore input från en flink programmerare, kördes den på 30-55ms, men om jag körde funktionen
flera gånger snabbt inpå gick körtiden ner till 10ms!
Försöka göra funktionen snabbare
Jag provade flera strategier för att få funktionen att köra snabbare
- Krympa koden (minification): Något snabbare vid första körning, sedan ingen skillnad.
- Ta bort funktioner och inkludera dem i koden (function in-lining): Ingen skillnad
- Byta ut Array's mot nativa objekt: 20-25% snabbare!
- Byta ut upprepade strängar mot variabler: 5% segare!
- Ge nativa variabler ett värde när de deklareras (type hinting): Något snabbare
- Ta bort delar (funktionalitet) av koden: Snabbare, så klart
- Ta bort return's: Ingen skillnad
- Ta bort variabler som inte användes: Ingen skillnad
- Ta bort "mellan"(onödiga)-variabler: Segare!
- Konvertera text-strängen till en array: Något segare
- switch i stället för if ... else if: Segare!
- Enkla if, i stället för else if -kedja: Ingen skillnad
- Gruppera if-satser som kollar samma sak: Ingen skillnad
En del resultat var väntade, och andra oväntade. Att kolla upp samma värde flera gånger kan vara snabbare än att spara det i en variabel! Anledningen är att processorn då slipper besöka minnet. När man optimerar kod ska man försöka undvika minnet och köra så mycket som möjligt i processorn. Det kan till exempel vara bättre att ha flera if-satser än att besöka minnet. Moderna processorer kör flera if-satser samtidigt (framåt i tiden).
Analysera endast ändrade delar
Nästa strategi var att endast gå igenom den del av filen som ändrats, och använda data från tidigare analys för resterande. Så nu laddar editorn endast om den funktion man ändrat, i stället för hela filen.
Undvika uppdatera DOM
Att uppdatera själva dokumentet, "document object model" (DOM) är segt. Och efter varje analys laddades funktion-listan om. Jag uppdaterade den till att endast ladda om, om funktionens namn eller argument ändrades, och då endast den enskilda option i HTML select.
Efter dessa tree uppdateringar: Optimering av analys-funktionen, endast analysera den ändrade funktionen, samt inte ladda om hela funktionslistan, fick jag följande resultat i samma fil på ca fyra tusen rader:
- Uppdatera filen i minnet: 5ms
- Analysera filen 1-2ms
- Bygga lista med funktioner: 0-1ms
- Uppdatera grafiken: 5ms
Totalt: 13ms. Och nu laggar det inte längre.
Jag har även några fler ide’er men har inte testat dem än då det inte behövs:
- Spara analys-data vid skriv-markören och sedan fortsätta analysera därifrån i stället från början.
- Inte analysera när man skriver innanför citat-tecken eller kommentar.
- Stänga av viss funktionalitet när det laggar.
- Flytta analys-funktionen till en egen process för att kunna köras parallellt.
- Använda data-strömmar för att ta upp mindre minne
Skrivet av Johan Zetterberg Juni 8, 2016.