Meten is weten
Een van de belangrijkste kernmerken van programmeren is het doorlopende proces van keuzes maken. Een puzzel waarbij je telkens een oplossing moet bedenken voor een bepaald probleem, en er bestaan altijd meerdere manieren waarop je een doel kunt bereiken. Elke manier kent wel bepaalde voordelen en dat maakt het nu juist zo moeilijk om te kiezen.
In de dagelijkse praktijk probeer ik mijn keuzes te maken op basis van logisch nadenken en ervaring. Ik kies voor een bepaalde oplossing waarvan ik veronderstel dat die de meeste voordelen biedt. Ik weeg meerdere aspecten tegen elkaar af, maar toch blijf ik vaak twijfelen over mijn beslissing. Heb ik wel de juiste veronderstelling gedaan?
Dan kan het zijn dat ik besluit om alsnog een testapplicatie te bouwen om te controleren of mijn ideeën over de voor- en nadelen kloppen. Dit kan er voor zorgen dat ik me neer kan leggen bij mijn keuze of dat ik besluit een verbetering aan te brengen. In beide gevallen draagt het bij aan een geruststelling van mijn gemoed.
Als mijn twijfels zijn weggenomen, voel ik me direct beter. Het laat me eindelijk los en ik gooi de test op de grote hoop waar het een stille dood sterft. En telkens als zich weer een dergelijk probleem voordoet en de twijfels weer de overhand nemen, bouw ik opnieuw een testapplicatie om me zekerder te voelen.
Met deze werkwijze doe ik me zelf en eigenlijk ook mijn medemens wel tekort. Elke keer weer opnieuw dezelfde soort afwegingen maken en de resultaten ervan weggooien. Ik heb me voorgenomen om meer structureel om te gaan met het bouwen van testapplicaties door de resultaten te documenteren, te archiveren en te publiceren, zodat ik zelf en mijn collega’s het resultaat kunnen hergebruiken. Uiteraard nodig ik iedereen uit om hieraan een bijdrage te leveren.
Het testperspectief
Belangrijk bij het maken van de juiste keuzes is het bepalen van het doel. Soms wil je alleen maar een oplossing met de beste performance, soms moet een oplossing ook inzetbaar zijn in een ander project en wil je een herbruikbare oplossing. Veel voorkomend is de onderhoudbaarheid: “Hoe kan ik op een elegante wijze mijn doel bereiken?”. Dit soort doelstellingen zijn vaak tegenstrijdig en toch wil je ze combineren. Daarom zal ik proberen aan te geven vanuit welk perspectief een bepaalde test is opgezet.
Appels met peren vergelijken
Bij het testen van verschillende code constructies begeef ik me per definitie op glad ijs. Ik heb lange tijd software ontwikkeld voor zowel de Mac als de PC. De software werd op beide platforms door verschillende runtime engines gedraaid. Op het ene platform was het if-statement sneller dan het case-statement, op het andere platform was het test resultaat precies andersom. Simpel weg omdat de implementatie van beide runtimes anders was.
Een andere ervaring die ik heb opgedaan met performance tests is dat er altijd wel een kantelpunt bestaat waarbij het voordeel de ene of de andere kant uitwijst. Ik maak mij dan ook geen illusie dat een test een definitief bewijs vormt voor de juiste keuze. Het maakt me echter wel bewust hoe bepaalde keuzes zich gedragen.
Try-catch versus if
Blind vertrouwen
Het try-catch mechanisme is zo iets moois dat ik bijna uit het oog ben verloren dat er wel degelijk kosten aan verbonden zijn.
De meeste objecten in .NET werpen diverse soorten excepties op als er iets mis gaat. Door met try-catch te werken kun je zeer compacte en heldere code schrijven, nl. door de pure ‘goed-situatie’ uit te schrijven in het try-block en de pure ‘fout-situatie’ in een catch-clause. Dit levert goed leesbare en dus onderhoudbare code op, omdat je je code niet hoeft te vervuilen met allerlei soorten check’s.
Ik had ooit gehoord dat .NET heel slim omgaat met try-catch en dat het nauwelijks performance zou kosten. Hierdoor heb ik me laten leiden door de voordelen van de elegante schrijfwijze. Ik begon zelfs try-catch te gebruiken voor situaties waarbij ik een waarde in een collectie zoek en op de IndexOutOfRangeExceptie een default waarde bepaal.
Effe checken
Toch bleef het door mijn hoofd spoken dat er een proces op gang gebracht zal moeten worden als je een try start. En het lijkt me logisch dat als er iets mis gaat, er exceptie objecten moeten worden gecreëerd. Kortom, ik kon niet langer leven met het idee dat ik niet op z’n minst één keer zou meten wat try-catch aan performance kost.
Ik ben mezelf dankbaar dat ik even de tijd heb genomen om een test te bouwen. Want ik weet wel waar ik een enorme performance winst kan bereiken in mijn applicaties. Kijk naar de test, het verschil is gigantisch.
Bewust kiezen
De documentatie van Microsoft zegt het volgende; “Try...Catch...Finally Statements
provides a way to handle some or all possible errors that may occur in a given block of code.”
Let wel, ik blijf try-catch echt wel veel gebruiken. Maar het bewust kiezen zit in het verschil; “some or all”. In situaties waarbij er eigenlijk maar één of enkele zaken zijn die mis kunnen gaan, zal de keuze voor het if-statement absoluut lonen.
Smit_PerformanceLab_1.zip (50 kb)