18 Bytes und die Kunst, Probleme zu lösen, die niemand hat

Steve Gordon jagt 18 fehlende Bytes durch BenchmarkDotNet und dotMemory. Ich erkläre, warum dieser Detektivsinn gut ist — und warum dieselbe Energie im Mittelstand selten dort landet, wo sie am dringendsten gebraucht wird.

⚙ KI-Entwurf Dieser Beitrag wurde automatisiert generiert und nicht redaktionell freigegeben. Behandelt ihn entsprechend.

Letztes Jahr, Auftrag bei einem Maschinenbauer in Nordbayern, 180 Mitarbeitende. Die interne Entwicklung hatte eine .NET-Applikation gebaut, die Fertigungsaufträge verarbeitet — und die war langsam. Nicht "theoretisch suboptimal", sondern spürbar langsam: Schichtleiter warteten im Schnitt neun Sekunden auf eine Auftragsliste, die eigentlich sofort kommen sollte. Ich bat um Profiling-Daten. Stille. "Profiling?" Niemand hatte je ein Profiling-Tool benutzt. Niemand wusste, wo der Flaschenhals lag. Man hatte stattdessen zwei Jahre lang vermutet, optimiert, geraten — und den Server mehrfach aufgerüstet.

Das ist das echte Mittelstands-Problem mit Performance. Nicht 18 Bytes.


Steve Gordon — bekannt durch seine tiefen Dives in .NET-Internals und ASP.NET Core — hat einen feinen kleinen Detektivroman geschrieben. Ausgangslage: Sein Benchmark über eine SQL-Parsing-Methode weist 312 Bytes Allocation aus. Sein Profiler (JetBrains dotMemory) sagt 294 Bytes. Visual Studio Performance Profiler bestätigt die 294. Wo sind die 18 Bytes? Gordon hätte die Diskrepanz abtun können — tut er aber nicht. Er gräbt sich durch den BenchmarkDotNet-Quellcode, stellt fest, dass das Framework GC.GetTotalAllocatedBytes(precise: true) verwendet, und beginnt dann, mit eigenen Messungen im Profiling-Harness die Lücke systematisch einzugrenzen. Der vollständige Artikel zeigt, wie man methodisch vorgeht, wenn Tools unterschiedliche Zahlen liefern: erst verstehen, dann urteilen.

Das ist echtes Handwerk, und ich meine das ohne Ironie.


Jetzt die KMU-Brille auf.

Die meisten .NET-Shops im Mittelstand, mit denen ich arbeite, bewegen sich in einem Fenster von 30 bis 300 Mitarbeitenden. Die Entwicklungsteams sind klein — oft zwei bis fünf Personen. Es gibt keine dedizierten Performance-Engineers. Es gibt keinen People-with-time-to-research. Was es gibt: einen Backlog, der nie kürzer wird, und irgendwo einen Senior, der BenchmarkDotNet kennt, weil er es mal in einem YouTube-Video gesehen hat.

Gordons Artikel lebt in einer Welt, in der du weißt, dass dein Code einen Allokations-Hot-Path hat, in der du BenchmarkDotNet bereits laufen hast, in der dein Profiling-Harness sauber isoliert ist — und in der 18 Bytes eine intellektuell interessante Frage sind. Das ist die Welt der Library-Autoren, der Framework-Maintainer, der Conference-Speaker, die ihren Demo-Code auf Herz und Nieren prüfen.

In meinem Maschinenbauer-Mandat war die Welt eine andere. Der echte Engpass lag in einer Schleife, die für jeden Fertigungsauftrag separat eine Datenbankverbindung öffnete und schloss — 400 Mal pro Auftragsliste. Nicht weil jemand das bewusst so gebaut hatte. Sondern weil der Code organisch gewachsen war und niemand je einen Flame Graph gesehen hatte. Die Lösung: Connection-Pooling richtig konfigurieren, die Schleife auf Batch-Queries umbauen. Ladezeit: von neun Sekunden auf unter 400 Millisekunden. Kein Micro-Benchmark. Kein Byte-Counting. Ein Nachmittag mit dotTrace und ehrlichen Augen.

Das ist keine Kritik an Gordon — das ist eine andere Problemklasse.


Was also nehme ich aus seinem Artikel mit, und was empfehle ich dir als KMU-Entscheider oder Entwickler in einem mittelständischen Team?

Erstens: Die Methodik ist Gold wert, auch wenn der Anlass zu akademisch wirkt.

Gordon zeigt exemplarisch, wie man mit widersprüchlichen Tool-Ausgaben umgeht: nicht raten, nicht ignorieren, sondern die Messung selbst hinterfragen. Das Prinzip gilt auch wenn dein Problem nicht 18 Bytes, sondern 9 Sekunden Ladezeit sind. Du misst mit einem Tool. Das Tool zeigt etwas. Du fragst: Misst dieses Tool wirklich das, was ich messen will? Im Mittelstand wird dieser Schritt fast immer übersprungen. Man sieht eine Zahl und glaubt ihr. Das ist der Anfang von vielen schlechten Optimierungen.

Zweitens: GC.GetTotalAllocatedBytes ist kein Exotica.

Auch wenn du nie im Leben einen Conference-Talk vorbereitest — dieser API-Call ist nützlich. Wenn du einen Hot-Path hast, den du schnell verifizieren willst, ohne ein vollständiges Profiling-Setup aufzubauen: eine kleine Konsolen-App, zwei Messpunkte, fertig. Gordons Harness-Code ist copy-paste-fähig und hat in drei meiner letzten Mandate als Schnelltest geholfen, bevor ich das große Profiling-Besteck rausgeholt habe.

Drittens: Der Aufwand muss zur Problemgröße passen.

Hier ist meine ehrliche Differenzierung: Wenn du heute in deiner .NET-Applikation einen Engpass hast, der Nutzer spürbar ausbremst — fang nicht mit Byte-Counting an. Fang mit einem Flame Graph an. Hol dir dotTrace oder den Visual Studio Performance Profiler, lass deine Applikation unter echtem Last laufen, und schau dir an, wo die Zeit hingeht. 80 Prozent der Probleme, die ich im Mittelstand sehe, liegen nicht im Managed Heap, sondern in I/O: unnötige Datenbankqueries, fehlende Indizes, synchrone Aufrufe wo async sein sollte, HTTP-Requests die in Loops stecken.

Erst wenn du den Engpass auf eine konkrete Methode eingegrenzt hast, die tatsächlich zu viel alloziert — dann lohnt sich das, was Gordon beschreibt. Dann ist sein Artikel ein exzellenter Leitfaden.

Viertens: Investiere in Mess-Kultur, nicht in Einzel-Optimierungen.

Der größte Unterschied zwischen den Teams, bei denen Performance-Arbeit nachhaltig wirkt, und denen, bei denen sie verpufft: Erstere haben einen Prozess. Sie wissen, wie man ein Baseline-Profil nimmt. Sie haben BenchmarkDotNet für kritische Pfade eingerichtet. Sie tracken Allocations über Releases hinweg. Das kostet initial ein paar Tage Aufwand — und spart mittelfristig die Hälfte der "warum ist das plötzlich langsam?"-Tickets.


Der vollständige Original-Beitrag von Steve Gordon: The Grand Mystery of the Missing 18 Bytes

Lesenswert — besonders der Teil, wo Gordon den BenchmarkDotNet-Quellcode aufschlüsselt. Das ist die Sorte Neugier, von der wir alle lernen können, auch wenn unser eigenes Tagesproblem zehn Größenordnungen gröber ist.


Wenn du gerade in deiner .NET-Applikation einen Engpass hast, nicht weißt wo du anfangen sollst, oder dein Team zwar Zahlen hat aber keine Interpretation — dann ist ein kurzes Gespräch manchmal der schnellste Weg.

30 Min Klartext-Sparring

— Bernhard