Compiler, interpreter en JIT: uitvoeringsmethoden vergeleken

Er zijn drie hoofdmanieren om broncode uit te voeren. Een compiler (ahead-of-time, AOT) vertaalt het hele programma naar machinecode vóór het wordt uitgevoerd. Een interpreter leest en voert het programma uit terwijl het draait, zonder een bestand met machinecode te maken. Een JIT-compiler (just-in-time) begint met interpreteren en compileert veelgebruikte delen tijdens het uitvoeren naar machinecode. Veel talen combineren deze methoden.

KenmerkCompiler (AOT)InterpreterJIT-compiler
Moment van vertalenVóór de uitvoering. Het hele programma wordt machinecodeTijdens de uitvoering. Het programma wordt gelezen en stap voor stap uitgevoerdTijdens de uitvoering. Veelgebruikte code wordt naar machinecode gecompileerd
OpstartenStart snel (maar eerst moet worden gebouwd)Start snel. Bouwen is niet nodigIn het begin langzaam, tot de code is opgewarmd (warm-up)
UitvoeringssnelheidHet snelst en voorspelbaarHet langzaamst. Vaak vele malen langzamer dan gecompileerde codeNa de warm-up dicht bij gecompileerde snelheid, en soms sneller door gebruik van runtime-informatie
PortabiliteitPer platform is een binary nodigGoed portabel. Werkt overal waar de interpreter beschikbaar isPortabele bytecode en een runtime per platform
FoutdetectieVeel fouten worden bij het compileren gevondenFouten komen naar voren als de betreffende regel wordt uitgevoerdAfhankelijk van de taal
GeheugengebruikWeinig runtime-overheadDe interpreter zelf blijft in het geheugenExtra geheugen voor de compiler en de cache met gecompileerde code
OntwikkelworkflowBewerken, bouwen, uitvoerenBewerken en direct uitvoerenMeestal bewerken en uitvoeren, of bouwen naar bytecode
Typische talenC, C++, Rust, GoTraditioneel Python (CPython), Ruby, shellscriptsJava (HotSpot), JavaScript (V8), C# (.NET), PyPy

De getalswaarden zijn typische ordegroottes en variëren per procesgeneratie en product.

Wanneer welke variant?

Compiler
Wanneer prestaties, compactheid en voorspelbaar gedrag belangrijk zijn. Besturingssystemen, games, embedded firmware.
Interpreter
Voor snelle experimenten, scripts en leren, wanneer ontwikkelsnelheid belangrijker is dan uitvoeringssnelheid.
JIT
Wanneer een portabel platform en snelheid bij langlopende programma's gewenst zijn. Webbrowsers en serverapplicaties.

Veelgestelde vragen

Is Python gecompileerd of geïnterpreteerd?

De standaardimplementatie CPython compileert broncode naar bytecode en voert die met een interpreter uit. Andere implementaties zoals PyPy voegen een JIT-compiler toe om sneller te zijn.

Is Java gecompileerd of geïnterpreteerd?

Beide. Java wordt vooraf naar bytecode gecompileerd, die de JVM tijdens het uitvoeren interpreteert of met JIT naar machinecode compileert.

Waarom is gecompileerde code snel?

Omdat het hele programma vóór de uitvoering naar geoptimaliseerde machinecode wordt vertaald en tijdens de uitvoering niets meer hoeft te worden geïnterpreteerd.

Wat is de warm-up van een JIT-compiler?

In het begin wordt het programma geïnterpreteerd, de vaak uitgevoerde code wordt herkend en daarna door de JIT gecompileerd. Tot die tijd is de snelheid lager.

Test uw begrip

Welk verschil tussen een compiler en een interpreter is juist?

  1. AEen compiler vertaalt vóór de uitvoering en een interpreter voert uit terwijl hij leest
  2. BEen compiler vertaalt regel voor regel tijdens de uitvoering en een interpreter vertaalt vooraf alles ineens
  3. CEen compiler behandelt alleen numerieke berekeningen en een interpreter alleen tekstverwerking
Antwoord en toelichting tonen

Antwoord: A. Een compiler vertaalt vóór de uitvoering en een interpreter voert uit terwijl hij leest

Een compiler vertaalt het hele programma vóór de uitvoering naar bijvoorbeeld machinecode en voert het vertaalde resultaat uit. Het vertalen kost tijd, maar de uitvoering is snel en er kan ook veel tijd aan optimalisatie worden besteed. Een interpreter interpreteert en voert het programma uit terwijl hij het leest, zodat snel kan worden geprobeerd, maar de uitvoering vaak traag is. In de praktijk worden ook veel gecombineerde methoden gebruikt, zoals eerst vertalen naar bytecode, die daarna wordt geïnterpreteerd, en vaak gebruikte delen met JIT compileren. Het onderscheid ligt niet in het soort verwerking dat kan worden uitgevoerd.

Welke uitspraak over een uitvoeringsomgeving die JIT-compilatie gebruikt is juist?

  1. AHet hele programma wordt vóór de uitvoering naar machinecode vertaald en dan gedistribueerd
  2. BTijdens de uitvoering vaak gebruikte delen worden naar machinecode vertaald en ook informatie van tijdens de uitvoering kan worden gebruikt
  3. CEr wordt helemaal geen machinecode gebruikt en bytecode wordt eindeloos instructie voor instructie geïnterpreteerd
Antwoord en toelichting tonen

Antwoord: B. Tijdens de uitvoering vaak gebruikte delen worden naar machinecode vertaald en ook informatie van tijdens de uitvoering kan worden gebruikt

Bij JIT-compilatie wordt eerst bytecode geïnterpreteerd en uitgevoerd, en wanneer delen die vaak worden uitgevoerd (hotspots) worden gevonden, worden deze tijdens de uitvoering naar machinecode gecompileerd. Met informatie van tijdens de uitvoering, zoals welke takken werkelijk worden genomen en welke types worden doorgegeven, zijn gedurfde optimalisaties mogelijk die bij vooraf compileren moeilijk zijn. Er is ook een mechanisme om terug te vallen op interpretatie als de aannames niet blijken te kloppen. Alles vooraf vertalen is AOT-compilatie (ahead-of-time), en uitsluitend interpreteren is een zuivere interpreter.

Wat is het belangrijkste voordeel van het gebruik in een compiler van een tussenrepresentatie (IR) die niet van de brontaal en niet van de CPU afhangt?

  1. AMet een tussenrepresentatie kan worden gecompileerd zonder de broncode te lezen
  2. BEen tussenrepresentatie kan door de CPU rechtstreeks worden uitgevoerd, zodat het genereren van machinecode overbodig is
  3. CDe voorkant per taal en de achterkant per CPU kunnen worden gescheiden en optimalisaties kunnen gemeenschappelijk worden gebruikt
Antwoord en toelichting tonen

Antwoord: C. De voorkant per taal en de achterkant per CPU kunnen worden gescheiden en optimalisaties kunnen gemeenschappelijk worden gebruikt

Bij ondersteuning van M talen en N CPU's zouden voor elke combinatie compilers nodig zijn, M×N in totaal, maar met een gemeenschappelijke tussenrepresentatie volstaan M frontends (van taal naar tussenrepresentatie) en N backends (van tussenrepresentatie naar CPU). Ook veel optimalisaties hoeven maar één keer op de tussenrepresentatie te worden gemaakt en zijn voor alle talen en CPU's bruikbaar. Een tussenrepresentatie kan niet rechtstreeks door de CPU worden uitgevoerd en moet ten slotte naar machinecode worden omgezet.

  1. Welke uitspraak over de rol van lexicale analyse in een compiler is juist?
  2. Wat doet de parsing (syntactische analyse) van een compiler?

Oefenvragen over Compilers

Belangrijke termen uitgelegd

JIT-compilatie (just-in-time)
Methode waarbij tijdens de uitvoering van het programma vaak uitgevoerde delen naar machinecode worden gecompileerd. Maakt optimalisatie op basis van runtime-informatie mogelijk. Wordt gebruikt in onder meer Java- en JavaScript-runtimes.

Verwante vergelijkingen