>_ DevTrendsde

Sprache

Start

Sprachen

Bereiche

Frontend Backend Mobile DevOps AI / ML GameDev Blockchain Embedded Sicherheit
C-sharp

Ultra Profiler kombiniert Low-Level-.NET-Trace-Sammlung mit Firefox-Profiler-Interface

Jedes Mal, wenn die Performance einbricht oder der Speicherverbrauch in einer .NET-Anwendung in die Höhe schießt, beginnt die altbekannte Suche. PerfView schreckt mit seiner Oberfläche aus den frühen 2000ern ab, dotnet-trace spuckt trockene Berichte aus, und voll ausgestattete kommerzielle Profiler entpuppen sich oft als schwere Geschütze. Kürzlich hat Alexander Mütel (bekannt als xoofx, Autor von Markdig und zahlreichen anderen Low-Level-C#-Utilities) sein Tool Ultra veröffentlicht, das versucht, detaillierte Trace-Sammlung mit einer benutzerfreundlichen Web-Oberfläche zu kombinieren.

Das Tool sammelt Low-Level-Samples bis hinunter zum OS-Kernel und zeigt die Ergebnisse über profiler.firefox.com an. Das Ergebnis ist ein leichtgewichtiges Kommandozeilen-Tool, das Traces von nur wenigen Megabyte Größe erzeugt und sofort eine klare Visualisierung mit Zeitachsen, Flamegraphs und Call-Trees öffnet.

Ultra Trace Screenshot

Was steckt unter der Haube und wie es funktioniert

Die Hauptidee hinter dem Projekt ist es, keine eigene sperrige UI zu erfinden. Der Autor nutzte die Firefox-Profiler-Engine, die bei interaktiven Graphen hervorragend abschneidet, und schrieb einen effizienten Datensammler für .NET.

Die Sammlung wird auf verschiedenen Plattformen unterschiedlich gehandhabt:

  • Auf Windows basiert das Profiling auf ETW (Event Tracing for Windows). Die Sampling-Frequenz kann hier bis zu 8.190 Samples pro Sekunde erreichen. Das gibt dir einen ehrlichen Call-Stack: Du siehst nicht nur verwalteten .NET-Code, sondern auch CLR-Runtime-Aufrufe, Aufrufe nativer Bibliotheken und Windows-Kernel-Funktionen.
  • Auf macOS arbeitet der Collector durch dynamische Bibliotheksinjektion direkt in den Prozess beim Start und lauscht auf EventPipe. Hier ist die Frequenz auf 1.000 Samples pro Sekunde begrenzt, und der Trace erfasst verwaltete und native User-Space-Aufrufe.

Im Bericht werden alle Aufrufe übersichtlich hervorgehoben und nach Kategorie geordnet: .NET, .NET JIT, .NET GC, .NET CLR, Native und Kernel. Es ist sofort klar, ob der Prozess in deiner Schleife kreist, auf einem Thread-Lock im Kernel wartet oder bei der Methodenkompilierung hängt.

Details zum Garbage Collector und JIT

Zusätzlich zu CPU-Samples hängt das Tool Runtime-Events an.

JIT-Kompilierungsmarker mit spezifischen Methodennamen erscheinen in der Zeitachse, sodass die Warmup-Phase der Anwendung klar sichtbar ist. Für GC zeichnet der Trace Heap-Statistiken, Runtime-Pause-Events (GCSuspendEE und GCRestartEE) und Speicherallokationen auf.

Die Traces sind kompakt: Ein zehnsekündiger Lauf wiegt normalerweise nur wenige Megabyte. Die resultierende Datei kann mit einem Kollegen geteilt oder direkt auf share.fox.dev für kollaborative Incident-Analyse hochgeladen werden.

Schnellstart

Das Tool wird als Standard-Global-Tool verteilt. Es erfordert .NET SDK 10 oder höher:

dotnet tool install -g Ultra

Auf Windows werden administrative Rechte benötigt, um Kernel-Stacks zu sammeln. Du kannst ein separates Programm mit dem Argumenttrennzeichen -- profilieren:

ultra.exe profile -- my_command.exe arg0 arg1

Wenn ein Dienst bereits auf einem Server oder lokal läuft, übergib einfach die Prozess-ID:

ultra.exe profile 15243

Nachdem die Sammlung mit Strg+C beendet wurde, speichert das Tool die Trace-Datei.

Auf macOS mit Apple-Silicon-Chips sind keine erhöhten Rechte erforderlich, aber es gibt einen Vorbehalt. Der Profiler funktioniert nur beim Start eines neuen Binärprogramms:

ultra profile -- ./my_command arg0 arg1

Das Anhängen per PID auf dem Mac ist noch nicht möglich, da der Collector ausschließlich beim Prozessstart injiziert. Kernel-Stack-Sammlung auf macOS wird ebenfalls nicht unterstützt, und Symbole aus Systembibliotheken im dyld Shared Cache bleiben unaufgelöst.

Integration mit Sprachmodellen

Ein interessantes Detail: Das Projekt-Ökosystem hat bereits einen separaten MCP-Server namens UltraMCP von Kirill Osenkov. Er verbindet Profiling-Ergebnisse direkt mit KI-Agenten wie Cursor oder Claude Desktop. Ein Agent kann den Trace selbst lesen, Engpässe im Code finden und Optimierungsvorschläge machen, ohne Stack Traces manuell in einen Chat zu kopieren.

Lohnt es sich, es zu probieren

Das Tool ist frisch, mit einer offenen BSD-2-Clause-Lizenz. Auf macOS gibt es noch funktionale Einschränkungen, aber für Windows ist es bereits ein großartiger Ersatz für schwere Utilities.

Wenn du regelmäßig herausfinden musst, warum ein Dienst langsam startet, wohin der Speicher in einer engen Schleife geht oder wie viel Zeit JIT benötigt, füge Ultra deinem Toolkit hinzu. Schnelle Trace-Sammlung mit einem einzigen Befehl ohne Fummelei an der Konfiguration spart eine Menge Zeit.

Ähnliche Projekte