Geheugen is belangrijk

Nog niet zo heel lang geleden werd het geheugen van een computer gemeten in megabytes en niet in gigabytes. Toen ik mijn eerste computer bouwde (een Sol-20), werd dat zelfs gemeten in kilobytes.

Er zaten 64 RAM-chips op dat bord en elke chip had 18 pinnetjes. Ik kan mij de exacte getallen niet meer herinneren maar ik kan mij nog wel heel goed herinneren dat ik elk pootje vast moest solderen. Als ik de boel verpestte, moest ik blijven hersolderen tot de geheugentest goed werd doorlopen.

Als je zoveel moeite moet doen voor RAM, leer je het te waarderen alsof het goud is. De jongeren vandaag de dag wijzen RAM lukraak toe. Ze laten pointers slingeren en schonen hun datastructuren niet op omdat geheugen tegenwoordig toch zo lekker goedkoop is.

Ze weten dat ze op een knop kunnen klikken en de hypervisor voegt zo 16 GB toe aan de cloud-instance. Waarom zou iemand die vandaag de dag programmeert zich nog druk maken om geheugen wanneer Amazon je zo 244 GB extra verhuurt?

Maar geheugensanering heeft ook zijn beperkingen, net zoals je ouders niet eeuwig je kamer willen opruimen. Je kan een grote heap toewijzen maar uiteindelijk zal je dat geheugen moeten opschonen.

En dan is er ook nog het gevaar van het virtuele geheugen. Je software zal 100 tot 1000 keer trager draaien als geheugen vol zit en je computer gaat swappen naar de harde schijf. Virtueel geheugen klinkt misschien geweldig op papier maar ontzettend traag in de praktijk.

Moderne programmeurs moeten ook door hebben dat geheugen vandaag de dag nog steeds waardevol is. Als ze dat niet door hebben zal de software, die zo snel loopt tijdens het ontwikkelproces zo traag als een slak worden als het veel wordt gebruikt. Je werk schaalt dan simpelweg niet goed. Tegenwoordig moet alles goed kunnen schalen. Beheer je geheugen voordat je software en dienst uit elkaar valt van ellende.

Op de volgende pagina: Trage computernetwerken

Computernetwerken zijn traag

Marketing-mensen roepen maar al te graag dat de cloud een soort computerhemel is waar engelen de data verplaatsen alsof het niks is. Als je je data wil opslaan, zijn ze bereid je een simpele webservice te verkopen die een permanente reservekopie van je data bewaren waar je je nooit meer druk om hoeft te maken.

Het kan inderdaad kloppen dat je je daar niet druk om hoeft te maken, maar je moet er zeker wel op wachten. Al het verkeer dat in en uit computers loopt, neemt tijd in beslag. Computernetwerken zijn een stuk trager dan het verkeer tussen de CPU en de lokale harde schijf.

Programmeerveteranen zijn opgegroeid in een tijd dat internet niet bestond. FidoNet routeerde je bericht door een andere computer te bellen die dichterbij het einddoel lag. Soms deed je data er dagen over om op de juiste plek te arriveren, piepend en krakend van modem tot modem.

Deze pijnlijke ervaring heeft oudgedienden geleerd dat de juiste oplossing zoveel mogelijk berekeningen lokaal uit te voeren en alleen wegschrijven naar een verre web dienst als alles zo klein en "final" mogelijk is. Jonge programmeurs zouden deze gedachtegang ter harte moeten nemen. Cloudopslag zou vermeden moeten worden tot aan de laatste milliseconde.

Compilers hebben bugs

Als er iets helemaal misgaat, zijn wij snel geneigd de code nogmaals te doorploegen. We vergeten wel eens iets te initialiseren of te zoeken naar een null pointer. Wat de reden ook mag zijn, elke programmeur weet dat, als onze software ermee kapt, het onze eigen domme schuld is, punt.

Dat hoeft echter niet altijd zo te zijn. Soms ligt het probleem bij de compiler of interpreter. Hoewel compilers en intrepeters relatief stabiel zijn, zijn ze niet perfect. Het heeft lang geduurd voordat de stabiliteit van de moderne compilers op het niveau is dat ze nu zijn. Jammer genoeg wordt deze stabiliteit tegenwoordig als vanzelfsprekend gezien.

Op de volgende pagina: Snelheid en het wereld wijde web

Gebruikers vinden snelheid belangrijk

Lang geleden hoorde ik dat IBM een usability-studie had gedaan en men kwam erachter dat mensen afgeleid raakten na 100 milliseconden. Is het waar? Ik vroeg het een zoekmachine maar het internet hing en ik vergat te refreshen.

Iedereen die ooit IBM's oude groenschermige applicaties vanaf een mainframe gebruikt heeft weet dat IBM z'n machines bouwde met de 100 milliseconden-regel in het achterhoofd. Als de mainframes verkocht werden zat er een spec sheet bij waarop je precies kon zien hoeveel I/O-kanalen er in de kast zaten (op dezelfde manier waarop autofabrikanten de cylinders in de motor tellen) Tuurlijk, de machines crashten af en toe nog wel, net als de moderne computers) maar als zij vloeiend liepen, stroomde de data vanuit de kanalen rechtstreeks naar de gebruikers.

Ik heb tenminste één keer gezien hoe een jonge programmeur het overdadige gebruik van Javascript-libraries dat een nieuw AJAX-project vertraagde verdedigde. Het is volgens hen niet eerlijk om hun slome innovatie te vergelijken met de oude terminals van weleer. De rest van het bedrijf moet stoppen met klagen. Ze krijgen er betere graphics en kleuren voor terug. En dat klopt. De applicatie ziet er prachtig uit. Maar gebruikers haten het omdat het zo traag is.

Het echte web is nooit zo snel als het bedrijfsnetwerk

Moderne websites kunnen ware tijdsverspillers zijn. Het kan soms enkele secondes in beslag nemen om alle megabytes grote JavaScript-libraries binnen te halen. De browser moet deze meer gelaagde megabytes ook nog eens door een JIT-compiler halen.

Het is een makkelijk gemaakte fout voor programmeurs die verliefd zijn op de browsergebaseerde tools die overal AJAX inzetten. Het ziet er allemaal prachtig uit in de demo op kantoor; de "server" staat immers onder het bureau of draait zelfs als localhost. Natuurlijk zijn de benodigde bestanden in een oogopslag binnen en ziet het er prachtig uit. Zelfs als de baas het test vanuit een ander kantoor.

Maar de gebruikers op dat DLS-lijntje of een mobiele verbinding via een overbelaste gsm-mast dan? Die wachten nog steeds op de libraries die langzaam maar zeker binnendruppelen. Als deze niet binnen een paar milliseconden binnen zijn, navigeren ze zo naar een andere site.

Op de volgende pagina: Algoritmische complexiteit en bibliotheken

Algoritmische complexiteit is belangrijk

Ik kwam ooit in de problemen toen ik een project uit handen gaf aan een jonge programmeur die Greasemonkey door en door kende. Hij herschreef onze en stuurde deze terug. Ik realiseerde dat hij de code eleganter had gemaakt maar tegelijkertijd de algoritmische complexiteit had verhoogd van O(n) naar O(n^2). Hij had de data in een lijst gegooid om het een en ander te matchen. Het zag er mooi uit, maar de boel vertraagde aanzienlijk naarmate n groter werd.

Algoritmische complexiteit is iets dat gelukkig bij IT-opleidingen wordt behandeld. Maar jammer genoeg zijn er veel middelbare schoolkinderen die dit niet oppikken als zij zichzelf Ruby of CoffeeScript aanleren in het weekend. Complexiteitsanalyse mag dan wel diepzinnig en theoretisch lijken, maar het kan een groot verschil opleveren als projecten worden opgeschaald.

Alles loopt vloeiend als n klein is, net zoals code snel wordt uitgevoerd als er genoeg geheugen beschikbaar is. Maar als het aantal gebruikers snel groeit, kan het wachten op een algoritme dat O(n^2) of zelfs O(n^3) is veranderen in een ware nachtmerrie.

Bibliotheken kunnen slecht zijn

De mensen die libraries schrijven doen dat niet altijd met jouw wensen en eisen in het achterhoofd. Ze proberen te helpen maar bouwen vaak iets dat werkt voor de hele wereld en niet iets dat alleen jouw kleine probleempje oplost. Er wordt vaak een Zwitsers zakmes gebouwd dat verschillende (versies van) je problemen oplost en niet iets dat is geoptimaliseerd voor jouw probleem. Het kan een goede oplossing zijn, maar het kan daarmee tegelijkertijd ook traag zijn.

Als je niet goed oplet, kunnen libraries je code enorm vertragen zonder dat je het door hebt. Er was ooit een jonge programmeur die mijn code uitlachte omdat ik tien regels had geschreven om tekens uit een string te halen.

"Ik kan dat met een regular expression schrijven in één regel code," zei hij stoer. Hij hield er echter geen rekening mee dat die ene regel code de regular expression moest parsen en reparsen als deze werd aangeroepen. Hij dacht simpelweg dat hij met één regel code een sneller programma had geschreven dan ik met m'n tien regels code.

Libraries en API's kunnen geweldig zijn als ze goed worden gebruikt. Maar als ze verkeerd worden gebruikt kunnen ze een verschrikkelijk effect hebben op de snelheid zonder dat je doorhebt waarom.