Developer Anthony kreeg onlangs te maken met een trage website van de klant waar hij voor werkt. Na wat onderzoek werd de oorzaak al snel duidelijk; een Memory Leak. Een term waar menig Software Developer niet mee te maken wil krijgen. Maar als we het niet altijd kunnen voorkomen, kunnen we wél de oplossing met je delen. 

Door Anthony Alberto 

Ik denk dat ik voor veel Software Developers spreek als ik zeg dat één van de leukste dingen in ons vak is dat wij het werk voor gebruikers makkelijker én efficiënter maken. We maken de gebruiker blij. Daarmee samenhangend; als er bugs in de software zitten, voel je je als Software Developer verantwoordelijk en wil je deze zo snel en goed mogelijk oplossen. Om een voorbeeld te geven; in de huidige Coronatijd worden er veel producten online besteld via webshops. Niets is zo vervelend als wanneer je iets wil bestellen, de website traag is. Veelal de grootste irritatie van online consumenten. Dit was recent het geval bij een applicatie waar ik betrokken bij was, voor het onderhoud. Na wat onderzoek werd al snel de conclusie getrokken; Memory Leak. Een term die wij Developers het liefst niet te horen krijgen. 

Want wat is een Memory Leak precies?

Memory, rechtstreeks vertaald naar het Nederlands, betekent ‘geheugen’, en in deze context die van een computer. Het is letterlijk waar je computer tijdelijke waardes (variabelen) opslaat vanuit verschillende programma’s. In het geval van een website is dit vaak de backend die op de server staat, waarmee de cliënt (webbrowser) communiceert. In code zeg je bijvoorbeeld:

var prijs = 9.95;

Dit wil dan zeggen dat het programma zolang het de prijs nodig heeft, dit tijdelijk opslaat in het geheugen. In het geval van een webwinkel zou zolang de bestelling in behandeling is, het programma dus de variabele nodig hebben. Maar zodra de variabele niet meer nodig is, wordt deze vrijgegeven in het geheugen. Op het platform, het Microsoft .NET Framework welke in dit geval specifiek is gebruikt, heet dit proces om variabelen op te ruimen “Garbage Collection.” Dit is een automatisch proces waar je in de meeste gevallen als ontwikkelaar geen rekening mee hoeft te houden. Echter, je kunt een code maken waarbij je een situatie creëert waarmee je impliciet zegt tegen de Garbage Collector dat een bepaalde variabele niet opgeruimd hoeft te worden. 

”Een trage webshop heeft vaak grote gevolgen voor de omzet”

In object-georiënteerd programmeren worden altijd objecten die we “classes” noemen, gebruikt. Een class kan bijvoorbeeld “Product” heten met een aantal eigenschappen als prijs, categorie, model en kleur.  Als je ooit een webwinkel zou maken, schrijf je deze class waarschijnlijk één keer in de programmacode. Echter is het zo dat als je meerdere programma’s gebruik wilt laten maken van hetzelfde object,  je deze beschikbaar kunt stellen in een onafhankelijke “Library “, zodat deze herbruikbaar is. Dit concept wordt veel gebruikt in softwareontwikkeling. Dit kan zowel met eigen geschreven codes alsmede een “Third Party”. Voordeel is dat je zelf geen code meer hoeft te schrijven. Een nadeel kan zijn dat je eigenlijk, als je niet de moeite neemt om dit grondig te bekijken, niet weet hoe die code in elkaar steekt. Omdat je ervan uitgaat dat deze goed functioneert. Ook speelt het gevaar dat als je een object creëert, welke ook weer een object van een Library gebruikt, er in de Library een stukje code zit waarin variabelen niet goed opgeruimd worden door de Garbage Collector. Het gevolg is dan dat je in je eigen code een afhankelijkheid hebt met externe code. Waarvan de Garbage Collector denkt dat deze niet opgeruimd hoeft te worden, waardoor je Memory bij elke aanroep meer geheugen alloceert en op een gegeven moment vol zal lopen. Dit betekent dat een Memory Leak traagheid van je webwinkel kan veroorzaken. En dat wil je niet! 

Hoe vind je snel een Memory Leak? 

Als een webwinkel traag is, kan dit grote gevolgen hebben voor de omzet. Daarom hebben veel professionele partijen monitoring software die onder andere de performance en response-tijden in de gaten houden. Zo was er in dit specifieke geval DynaTrace, welke ons waarschuwde dat het Memory volliep. Het nadeel van de tools is vaak dat ze constateren dat Memory volloopt en ze globaal kunnen aangeven waar het probleem zit. Hiermee heb je een indicatie waar het probleem ligt, maar kun je het probleem vaak nog niet oplossen. omdat dit in de praktijk, afhankelijk van de complexiteit, om honderden of duizenden regels code gaat. Zoeken naar de spreekwoordelijke speld in de hooiberg dus.

Als ontwikkelaar weet je vaak wel wat de meest verdachte objecten zijn in code en loop je deze als eerste na op verdachte dingen. Ook kun je altijd de applicatie op je eigen omgeving “debuggen”. Dit is het stap voor stap door je code heenlopen om te kijken wat de code precies doet. Echter verschilt bijvoorbeeld het aantal verzoeken en de data die je gebruikt vaak sterk van wat op de productieomgeving draait en is het vaak lastig om de situatie enigszins te reproduceren. Gelukkig zijn er tools die daarbij kunnen helpen, zoals Resharper .Memory en de Memory Profiler van Visual Studio; de meestgebruikte ontwikkeltool van .NET Developers. Wél is hiervoor de Enterprise-editie nodig. Met deze tools kun je met snapshots (een soort foto van een bepaald moment van je geheugen) exact zien welk object hoeveel geheugen in beslag neemt. Als je dan twee snapshots vergelijkt, zie je welke objecten opgeruimd worden en welke overleven. In de praktijk gaat het vaak om honderden objecten en is het lastig te bepalen of het programma deze nog nodig heeft of niet. Daarnaast heb je nog het probleem dat wanneer je dit lokaal op je eigen omgeving uitvoert, je dus de exacte situatie niet kunt nabootsen zoals deze op de productieomgeving is, welke het probleem veroorzaakt. 

”in de praktijk is het zo dat als de boosdoener gevonden is, de oplossing vaak relatief simpel is”

Wat je eigenlijk wilt, is een snapshot van je productieomgeving en gelukkig is dit mogelijk in de vorm van een Memory dump (.dmp file) van je applicatie op de server waar deze op draait. Het meeste ideale is dan natuurlijk ook op het moment dat het probleem zich voordoet. Als je deze file uitleest, kun je pinpointen welk object niet opgeruimd wordt en dus veel Memory in beslag neemt. Dan wijs je je hoofddader aan. Nu je weet op welk punt je de problemen verwacht, kun je wél lokaal debuggen en de snapshots maken en gericht kijken of het Memory oploopt. Als dit dus het geval is, heb je je speld gevonden!

Hoe los ik een Memory Leak op? 

Zo, de boosdoener is gevonden. In de praktijk is het zo dat als de boosdoener gevonden is, de oplossing relatief simpel kan zijn. De uitdaging zit hem dus voornamelijk in het vinden van de boosdoener. Per boosdoener is de oplossing natuurlijk heel specifiek. Voor de technische mensen onder ons; in dit specifieke geval werd er een “static” variabel van het type “DataTable”, wat uit verouderde .NET(SQL) Libraries komt, gebruikt. Deze bleef in het geheugen staan en werd dus niet opgeruimd. De oplossing was in dit specifieke geval de variabele “handmatig” op te ruimen. Dat betrof letterlijk het toevoegen van één regeltje code; “dataTable.Clear()”. Hierna is het een kwestie van het met je tool opnieuw snapshots maken en vaststellen dat het Memory niet meer oploopt en de Memory Leak is opgelost.

Tot slot; vaak komen zaken als Memory Leak ongelegen, omdat ze juist naar boven komen in de drukste periodes. Dan zijn de systemen het zwaarst belast, wat het probleem ook bedrijfskritisch kan maken. Er komt dus aardig wat druk op de Developer die het snel en gedegen moet oplossen. Ook al mag de oplossing klein zijn, het effect van de voldoening en samenhangend de blije gebruikers, wordt daardoor niet minder groot.

En dat is toch waar ons vak veel om draait; het werk voor gebruikers makkelijker én efficiënter maken!

Meer verdieping nodig? Check dan deze links:

Over de auteur:

Anthony Alberto is onze deskundige .Net ontwikkelaar en met vijftien jaar programmeer-ervaring leert hij iedereen nog elke dag bij over softwareontwikkeling. En daar schrijft hij dan ook graag over. 

Gerelateerd

Meer innformatie?

Wil je meer weten over Zo vind je snel de oorzaak van een Memory Leak (en los je hem op!), neem dan contact met ons op.