De benchmarkpocalypse
Hoewel het makkelijker dan ooit is geworden om serieuze prestatiewinst te behalen, is het ook makkelijker dan ooit om een benchmark te "reward hackken" en neprestaties te genereren. Dat eerste gebeurt waarschijnlijk stilletjes bij veel verschillende bedrijven, maar dat laatste zie ik tegenwoordig minstens één keer per week. Iemand claimt dat ze X hebben geoptimaliseerd en een enorme prestatieverbetering hebben behaald ten opzichte van bestaande software, maar wanneer je er naar kijkt, blijkt dat ze een optimalisatie hebben toegepast die de benchmarkprestaties verbetert zonder de prestaties in de echte wereld daadwerkelijk te verbeteren. Dit gebeurt vaak bij projecten in de trant van "we hebben X herschreven in Rust" of door nieuwe startups die kapitaal willen aantrekken of iets willen verkopen, maar het gebeurt ook bij andere soorten projecten.
Natuurlijk hebben mensen altijd al niet-representatieve microbenchmarks gebruikt om aan te tonen dat hun project geweldig is. Het is altijd makkelijk geweest om een niet-representatieve microbenchmark te simuleren en dat zal nooit veranderen. Wat wel is veranderd, is dat het vroeger veel werk kostte om een grote benchmarksuite te manipuleren, maar een LLM in een loop kan dat nu eenvoudig doen. Er zijn enkele bekende voorbeelden van het manipuleren van grote benchmarksuites uit de tijd dat dit nog moeilijk was. Zo probeerden CPU-leveranciers, toen mensen nog keken naar SPECint / SPECfp als graadmeter voor workstation-prestaties, compiler-optimalisaties te vinden die de berekening in de benchmark versnelden; zo vond Sun een manier om 179.art met 12x te verbeteren in SPECfp2000. Bekwame ingenieurs besteedden veel tijd aan het vinden van dergelijke benchmark-hacks. LLM's maken dit triviaal, waardoor voorheen betrouwbare benchmarks betekenisloos worden, tenzij je het resultaat auditeert of iemand vertrouwt die dat heeft gedaan.
In plaats van te wijzen naar de slechte claim van iemand anders, wijs ik naar FRE, een regex-engine die ik door een agent heb laten bouwen. Ik zou kunnen claimen dat dit de snelste regex-engine ter wereld is, omdat hij de Rust regex crate verslaat in de vrij uitgebreide rebar regex-benchmarksuite. Maar FRE is gecreëerd door een agent een maand lang in een loop te zetten met de instructie om niet te overfitten op de benchmark, maar zonder echt toezicht. Voor het grootste deel is het vrij eenvoudig om een LLM een goede benchmarkscore te laten behalen, en deze casus was niet anders; het duurde een paar weken om de prestaties van de Rust regex crate ongeveer te matchen en nog eens een paar weken om 1,4x sneller te worden op rebar. Maar agents zijn geneigd tot reward hacking en overfitting tenzij je strikte vangrails instelt, wat ik in dit experiment niet heb gedaan.
Om te controleren op overfitting, heb ik (sommig wat arbitrair) het ripgrep-benchmarkcorpus gebruikt als een holdout-benchmark. Het resultaat was dat FRE 10x langzamer was in gevallen waarin de benchmark niet oneindig duurde door een algoritmische explosie, en er waren gevallen waarin het zo lang duurde dat het niet redelijk was om zelfs maar te wachten tot de benchmark voltooid was. Dat is dus wat we zeggen van "40% sneller"!
De rebar benchmarksuite van Andrew Gallant (aka BurntSushi) is vrij uitgebreid voor benchmarksuites, maar zelfs met zo'n suite hebben agents geen probleem om een hoge score te behalen terwijl ze overfitten op een manier die niet noodzakelijkerwijs leidt tot goede algemene prestaties.
De volgende stap was het gebruik van een truc die we eerder hebben besproken: niet alleen de LLM vertellen dat hij niet mag sjoemelen, maar dat er een holdout-benchmarkset is waartegen hij wordt beoordeeld. Daarna generaliseerde de LLM de prestaties matig, tot het punt waarop het ongeveer 2,4x langzamer is over de hele linie op de holdout. Dat klinkt best goed, gezien we het vergelijken met de snelste general-purpose regex-engine die bestaat. Maar onthoud dat deze benchmarks zijn gemaakt door een coding agent. Als ik kijk naar wat de benchmarks meten, is het voor sommige van hen eigenlijk onlogisch om ze op te nemen, althans met een gelijk gewicht. Als we alleen kijken naar de benchmarks die er echt toe lijken te doen, is FRE 4x langzamer op de holdout, wat veel beter is dan vóór het toepassen van de "vertel ze dat je een holdout hebt"-truc, maar nog steeds ver verwijderd is van 40% sneller.
Er zijn een paar dingen die ik interessant vond:
- Het is triviaal om een niet-triviale benchmark te "winnen" op een betekenisloze manier, zelfs wanneer je agents instructies geeft om niet te reward hackken of te overfitten.
- Opnieuw bleek dat de LLM vertellen dat er een holdout-set is, beter werkte dan de LLM simpelweg vragen om gegeneraliseerd werk te leveren of niet te overfitten of te sjoemelen.
- Hoewel de algehele prestaties van
FREniet zo goed zijn, presteert het voor sommige specifieke use-cases wel beter; over het algemeen zijn de kosten voor het schrijven van gespecialiseerde code, waarvoor vroeger serieuze engineering-ervaring nodig was, enorm gedaald.
Wat betreft punt (1): het is geen wonder dat ik zoveel onzinclaims zie. In het verleden zou je een aanzienlijke hoeveelheid expertise nodig hebben om iets als FRE te bouwen dat prestaties goed genoeg faked om onterecht een snelheidswinst van 40% te claimen. Je zou minimaal een goed begrip moeten hebben van string-matching algoritmen, regex-engines, algemene code-optimalisatie en SIMD-optimalisatie. FRE heeft ook een modus waarin de regex wordt gecompileerd naar machinecode, dus je zou ook expertise in compilers nodig hebben. Nu kun je dit soort benchmark-valsspel (of je het nu wilt of niet) bereiken met een paar minuten typen.
Wat betreft punt (2): ik ben benieuwd of dit generaliseerbaar is, maar ik heb nog niet genoeg voorbeelden geprobeerd om dat te kunnen zeggen.
Wat betreft punt (3): er is geen reden om een vibe-coded regex-bibliotheek te gebruiken die met bijna geen menselijke inspanning is gemaakt en die langzamer is dan een robuuste, bestaande en goed geteste bibliotheek, dus ik vind het FRE-artefact zelf niet interessant. Wat ik wél interessant vind, is in hoeverre LLM's een vervanging kunnen zijn voor wat vroeger zeldzame, gespecialiseerde en dure kennis was.
Vroeger zou je, zelfs als je de kennis had, waarschijnlijk geen custom regex-engine schrijven die is geoptimaliseerd voor jouw specifieke workload. Er zijn sommige grootschalige use-cases waar mensen dat wel zouden doen. Toen ik bijvoorbeeld aan de Bing-index werkte, bevatte de code meerdere verschillende compilers omdat iemand die eraan werkte maximale prestaties wilde behalen; aangezien je bij een zoekmachine om zowel compiletijd als gecompileerde prestaties geeft en de afwegingen per plek verschillen, behaal je betere prestaties door een custom compiler te schrijven voor elke plek waar een normaal project gewoon een interpreter zou gebruiken of direct een datastructuur zou doorlopen met "normale code". De persoon die die compilers schreef, zou wellicht ook meerdere custom regex-engines schrijven, maar zeer weinig mensen hebben zowel de expertise als de neiging daartoe, laat staan de vrijheid om zoveel tijd aan dergelijke gespecialiseerde code te besteden voor hun werk. Als je de kosten van die Bing-ingenieur (destijds een Partner-level engineer, later gepromoveerd tot Distinguished Engineer vanwege het werk aan de zoekindex) afzet tegen de kosten van het draaien van een LLM in een loop, zijn de kosten voor het schrijven van dit soort gespecialiseerde code met vele grootteordes gedaald.
Hoewel de algehele FRE regex-engine slechtere prestaties heeft dan de Rust regex crate, betekenen de winsten die je kunt behalen door te specialiseren voor jouw workload dat het in sommige gevallen redelijk kan zijn om je eigen gespecialiseerde regex-engine ergens in te voegen, en hetzelfde geldt voor diverse andere soorten low-level software. Je hoeft geen AI-maximalist te zijn om te denken dat het aannemelijk is dat we binnen enkele jaren dit soort dingen zullen zien gebeuren voor grotere systemen, zoals databases.
Bedankt aan Yossi Kreinin, Jamie Brandon, Peter Geoghegan, Luke Burton, John Spurling, Dennis Snell en Max Bittker voor de opmerkingen/correcties/discussies.
P.S. Naar aanleiding van de discussie hier: met LLM's is de tijd die het kost om ergens kort in te duiken en mijn nieuwsgierigheid te bevredigen enorm afgenomen, terwijl de tijd die het kost om iets uit te schrijven en rigoureus genoeg te maken om op mijn blog te publiceren niet echt is veranderd (om verschillende redenen is die zelfs toegenomen). Het resultaat is dat ik meer analyses doe dan ooit en de resultaten met een paar vrienden deel, maar ze niet publiceer. Als experiment probeer ik sommige dingen nu zeer snel uit te schrijven, met een veel lagere standaard voor hoe "schoon" en rigoureus het is dan ik normaal zou hebben voor iets op de blog; meer zoals wat ik een vriend in een informeel gesprek zou vertellen. Het doel voor dit bericht was om het uit te schrijven in ongeveer een half uur, zodat ik het tijdens de lunch zou kunnen doen. Als je hier een mening over hebt, laat het me weten!
Natuurlijk is een kanttekening hierbij dat alle cijfers een hoger risico lopen onjuist te zijn dan gebruikelijk. Ik keek misschien een minuut of twee naar een benchmark en vond een fout, daarna keek ik naar een andere benchmark en vond ik weer een fout. Beiden zijn inmiddels opgelost, maar dit impliceert dat er andere fouten zijn die ik niet de tijd heb genomen om op te sporen. Maar wat betreft slechte benchmarkcijfers is dat juist zeer realistisch! Bijna elke keer dat ik naar benchmarkcijfers kijk, zijn de cijfers onjuist. Een ander aspect van de benchmarkpocalypse is dat LLM's,althans voor nu, goed zijn in het uitvoeren van slechte benchmarking. Zelfs als je iets hebt dat een echte prestatieverbetering is, kun je dat over het algemeen niet afleiden uit een door een LLM gegenereerde benchmark-setup, tenzij er aanzienlijke zorg is besteed om er zeker van te zijn dat de setup redelijk is.
***
Appendix: Meer details over de FRE-benchmarks
Iets wat ik ontdekte nadat ik het bovenstaande schreef maar voordat ik het publiceerde, was dat de claim van de LLM dat FRE 40% sneller was dan de Rust regex crate op rebar ook onjuist was. Of, als het niet onjuist was, dan was het in ieder geval misleidend. Het voerde de benchmarks niet uit op dezelfde manier als de rebar-benchmarks werden uitgevoerd. Na een minuut controleren vond ik twee problemen. Het blijkt dat de LLM, ondanks instructies om de rebar-benchmarks uit te voeren zoals ze worden gedaan in de officiële repository, de interface had gewijzigd om FRE bepaalde optimalisaties toe te staan die de prestaties verbeterden. Na het herstellen hiervan was FRE niet 1,4x sneller dan Rust op rebar, maar 1,5x langzamer (en "slechts" twee keer zo snel als re2), dus het oorspronkelijke resultaat was dubbelop nep: niet alleen was FRE sterk overfit op de rebar-benchmarks, maar de resultaten bevatten ook valsspel.
Aan de positieve kant betekent dit dat het verschil in prestaties tussen FRE op rebar (1,5x langzamer dan Rust) en op de holdout-benchmarks (2,4x langzamer) niet zo groot is als het eerst leek, dus de "vertel de LLM dat je een holdout hebt"-truc werkte zelfs beter dan gedacht.
Daarna liet ik een LLM een paar uur "hill climb" en claimde deze dat FRE 1,28x sneller was. Dat klinkt als een geweldige verbetering voor slechts een paar uur LLM-tijd, maar toen besloot ik nog een minuut te zoeken naar valsspel en vond ik meerdere problemen, waaronder een geval waarin een zoekopdracht naar het aantal matches van (?s)^(.)$ het aantal teruggaf zonder zelfs maar naar de data (de haystack*) te kijken. Een ander geval van valsspel was het uitvoeren van een multi-line grep, terwijl de benchmark per regel had moeten worden gedaan. Het vinden hiervan is niet verrassend, want dit is wat er gebeurt als je een agent een maand in een loop laat draaien zonder strikte vangrails. Of dit mijn punt sterker maakt of ondermijnt is onduidelijk, maar na het oplossen van deze reeks problemen was FRE weer 1,4x langzamer. Na een agent een nacht te hebben laten draaien, was FRE naar verluidt weer 1,5x sneller.
Aangezien mijn oorspronkelijke doel was om te zien wat er gebeurt als je een huidige (publieke) SOTA-agent (GPT-5.6 Sol) in een loop draait zonder veel supervisie op een niet-triviaal code-optimalisatieprobleem, stop ik hier en voeg ik een paar plots van de resultaten toe, in plaats van meer tijd te besteden aan het eerlijker maken van de benchmarks.
Over het algemeen kunnen we zien dat FRE ten opzichte van Rust en RE2 beter presteert op de rebar-benchmarks (en zoals vermeld is veel hiervan te wijten aan overfitting), maar niet over de hele linie.
Er is ook een AOT-compiler-modus die er lang over doet om een regex naar native code te compileren voordat deze wordt uitgevoerd. Er is geen AOT-ondersteuning voor alles, maar de resultaten laten zien dat de AOT-compiler erg traag is (hij verliest zwaar in de benchmarks voor compiletijd) en, ondanks de tijd die in het compileren gaat zitten, zijn de resultaten vaak langzamer dan met de standaard FRE regex-engine (hoewel hij in veel gevallen ook sneller is).
En dan zijn er de holdout-benchmarks. Zoals vermeld presteert de non-AOT FRE-code op de holdout minder goed dan op rebar. Gezien het feit dat dit gaat over een workload zoals ripgrep, is de "hot search"-set van benchmarks waarschijnlijk belangrijker dan de andere, waardoor het FRE-resultaat slechter is dan de algehele score doet voorkomen.
Eén ding om op te merken is dat voor de holdout-benchmarkgevallen waarin we compiletijd niet meerekenen en we herhaaldelijk zoekopdrachten uitvoeren, AOT FRE beter presteert. Voor veel use-cases wil je geen regex die meerdere seconden kost om te compileren, maar er zijn genoeg gevallen waarin dit prima is. Bijvoorbeeld voor iets als ripgrep of Silver Searcher: het zou kunnen starten met een regex die direct kan matchen, en ondertussen in een andere thread compileren en overschakelen naar de snellere matcher zodra de compilatie klaar is. Gezien hoeveel van mijn CPU wordt verbruikt door lange ripgrep-zoekopdrachten, lijkt het me dat zo'n strategie de prestaties voor mijn persoonlijke werk zou kunnen verbeteren. Vóór LLM's zou het waarschijnlijk niet zinvol zijn om de moeite te doen een optimaliserende regex-compiler te schrijven, maar dit is nu mogelijk met een paar tokens.
Een ander punt is dat deze vergelijking betwistbaar onfair is, omdat deze is uitgevoerd op een ARM Graviton-machine met SVE/SVE2 en FRE SVE/SVE2-optimalisaties heeft. Vóór LLM's was het wellicht de moeite niet waard om regexes te optimaliseren voor elke combinatie van SIMD-instructies die er bestaat, maar met LLM's is het vrij eenvoudig om redelijke SIMD-optimalisaties te genereren. Ik ken menselijke experts die kunnen bevestigen dat ze LLM's hierin overtreffen; Jay Stelly zei bijvoorbeeld dat de laatste keer dat hij een LLM probeerde SIMD-code te laten produceren, het 20 iteraties kostte om de code zo goed te krijgen als hij wilde. Maar aan de andere kant hebben LLM's de capaciteit om meer optimalisaties te proberen dan een mens in enige hoeveelheid tijd zou kunnen, waardoor ze over het algemeen toch goed kunnen presteren, zelfs als een specifieke optimalisatie niet zo goed is als die van een menselijke expert.
Dan is er nog het probleem van overfitting. Afhankelijk van de context is dat probleem variërend van zeer eenvoudig tot enigszins moeilijk op te lossen. Ik heb er bewust niet hard voor geprobeerd om dit op te lossen om te zien wat er zou gebeuren, maar ik ben er wel in geslaagd zonder overmatige inspanning toen ik aan Azul AI werkte. Veel van deze grote benchmark-claims komen echter voort uit situaties waarin mensen weinig tot geen moeite hebben gedaan om overfitting te voorkomen, of zelfs negatieve moeite. In het pre-LLM-tijdperk kozen mensen vaak zeer niet-representatieve microbenchmarks om te laten zien hoe geweldig hun project was, wat (althans onbewust) neerkomt op negatieve moeite om overfitting te voorkomen. Gezien de menselijke natuur denk ik niet dat mensen zullen stoppen met het maken van misleidende claims, en omdat het makkelijker is geworden om deze claims te maken, zien we er natuurlijk meer van.
Merk op dat hoewel dit bericht niet-AI-software heeft besproken, alles wat hier gezegd is dubbel zo opgaat voor AI-software. Ik heb bijvoorbeeld veel mensen reacties zien plaatsen dat Kimi K3 op het niveau van Fable (5) zit. Maar iedereen die ik ken die het heeft gebruikt, vond het substantieel slechter dan GPT-5.6 Sol en Fable. Ik zeg niet dat het geen indrukwekkende prestatie is, maar de prestaties in een breed scala aan echte taken zijn niet op het niveau dat in benchmarks wordt getoond. Dit geldt zelfs voor evaluatieproblemen, zoals wanneer een vriend verschillende coding agents probeerde op de ICFP 2026 wedstrijdproblemen. Het geldt ook voor security-problemen; een collega van mij probeerde Kimi K3 te gebruiken om kwetsbaarheden in onze software te scannen en ontdekte dat het ongeveer een kwart van de kwetsbaarheden vond die GPT-5.6 Sol vond, geen kwetsbaarheden vond die GPT-5.6 Sol niet vond, en geen voordelen had in enige dimensie behalve de kosten. De mensen die ik ken die goedkopere modellen gebruiken om echte security-problemen te vinden, gebruiken andere modellen, zoals GLM-5.2, die slechter presteren op benchmarks maar beter in de praktijk.
Terug naar FRE: nog een opmerking is dat de holdout-benchmark een arbitraire subset is van de ripgrep-benchmarksetup die door een agent is gekozen om onbekende redenen. Ik heb een agent gevraagd de volledige benchmarksuite op te halen, maar dat was niet af voor dit bericht, dus ik weet niet wat het resultaat zal zijn zodra dat voltooid is.
Ironisch genoeg heb ik veel vertrouwen in sommige projecten waar mensen het meest sceptisch over zijn, zoals pgrust. Elke keer als ik pgrust ergens zie, zijn er veel sceptische reacties. Maar zonder in detail te hebben gekeken naar wat hij optimaliseert, vertrouw ik erop dat ze niet sjoemelen met hun benchmarks, omdat Michael Malis het project is gestart (en nog steeds betrokken is). Ik keek vroeger naar de meeste benchmark-claims die ik tegenkwam in detail, maar er zijn er nu zoveel dat ik daar simpelweg geen tijd meer voor heb en over het algemeen ervan uitga dat claims in geest onjuist zijn (zelfs als ze technisch correct zijn), tenzij er een reden is om anders te geloven. Natuurlijk zal dit soms fout zijn, maar LLM's zijn zo'n ongelooflijke machine voor het uitvoeren van een "DoS op menselijke aandacht" dat ik niet weet wat ik anders zou moeten doen (ik heb geprobeerd LLM's prestatieclaims te laten analyseren, en hoewel het resultaat correleert met wat ik zelf zou denken, is het resultaat vaak onjuist).
Iemand kan in enkele seconden (of zelfs helemaal geen tijd, bij gebruik van het juiste framework) iets genereren waar mensen minuten tot uren aan nodig hebben om het te begrijpen. Dit is een onderwerp voor een ander bericht, maar uit gesprekken met mensen over hun ervaringen op de werkvloer blijkt dat bedrijven met slechte normen voor dit soort zaken vandaag de dag echt worstelen met productiviteit.
***
Voetnoten:
- Dit verwijst naar het geometrisch gemiddelde van alle
rebar-benchmarks. Dit is waarschijnlijk niet de juiste metriek, omdat dit impliciet stelt dat elke benchmark even belangrijk is, wat waarschijnlijk niet het geval is. In tegenstelling tot iets als SPEC CPU, positioneren derebar-benchmarks zich niet als iets waar je een betekenisvolle samenvattende metriek krijgt die de algehele prestaties representeert (de repo merkt zelfs op dat het "een bevooroordeelde barometer is voor het peilen van de relatieve snelheid van sommige regex-engines op een gecureerde set taken"). Om een getal te krijgen dat een nuttige samenvattende metriek is, zou je veel moeten weten over hoe mensen regexes in de praktijk gebruiken, en ik weet daar nagenoeg niets over. Voor zover ik weet, zou je twee verschillende getallen moeten hebben (zoals SPECfp en SPECint voor SPEC CPU), of tien of honderd, omdat er allerlei verschillende manieren zijn waarop mensen regexes toepassen.
- De eerste paar regex-benchmarks waar ik naar keek waren al opgenomen in
rebar, dus die zouden niet werken als holdout. En zoals eerder besproken zijn huidige SOTA LLM's niet erg goed in benchmarking, dus ik zou de LLM niet kunnen vertrouwen om zelf een holdout-benchmark te bedenken, tenzij ik genoeg wist over regex-prestaties om de kwaliteit van de benchmarksuite te kunnen beoordelen. Aangezien ik nagenoeg niets weet over string-matching algoritmen of regex-prestaties, was dat ook geen optie. Het blijkt dat BurntSushi ookripgrepen de benchmarks voorripgrepbeheert, die groot genoeg zijn om niet inrebarte zijn gebundeld, dus ik heb geprobeerd die benchmarks als holdout te gebruiken.
Groetjes,