Mert Özen Further With Every Line

Blog

Mert Özen's blog posts on software development, backend, frontend, and DevOps.

Series
43 posts found
What Changed in Diagnostics from .NET 8 to .NET 11: The System.Runtime Meter, New dotnet-trace Profiles, collect-linux, Runtime Async Stacks and In-Process Crash Reports
Developer Tools PART 10

What Changed in Diagnostics from .NET 8 to .NET 11: The System.Runtime Meter, New dotnet-trace Profiles, collect-linux, Runtime Async Stacks and In-Process Crash Reports

.NET 9 replaced the old EventCounters with the System.Runtime Meter, .NET 10 brought new dotnet-trace defaults and collect-linux, and .NET 11 added lossless event buffering, runtime async and in-process crash reports. We give a mapping table from old to new metric names and show, with real runs on .NET 10 and 11, the cpu-sampling and Block mode errors, runtime async stacks before and after a suspension, and crash report output.

14 Nov 2026 11 min 3
Diagnose, Fix, Prove: An End-to-End Performance Case in Bookstore
Developer Tools PART 09

Diagnose, Fix, Prove: An End-to-End Performance Case in Bookstore

The way to solve a performance problem is to measure in order: a wide view with dotnet-counters, the hot path with dotnet-trace, the growing type with gcdump, then proof with BenchmarkDotNet and k6 under the same load. We find that what pushes Bookstore checkout's p99 to 537 ms is not the new JsonSerializerOptions the code review blamed but reading 2,000 rules on every request and a cache that never gets a hit, bring p99 down to 1.5 ms and give a report template.

14 Nov 2026 11 min 3
Diagnostics in Production: dotnet-monitor, Collection Rules, Kubernetes Sidecars and Continuous Profiling
Developer Tools PART 08

Diagnostics in Production: dotnet-monitor, Collection Rules, Kubernetes Sidecars and Continuous Profiling

dotnet-monitor collects traces, gcdumps and dumps through an HTTP API and collection rules, so nobody has to get into the container; rules need Listen mode, and security needs a localhost-bound API, an API key and restricted egress. We run Bookstore with a sidecar on kind, measure rules triggered by slow report requests and by our own meter, the throttling of Limits and the suspend/nosuspend difference, and look at the alpha status of OpenTelemetry Profiles.

14 Nov 2026 11 min 2
Visual Studio and Rider Profilers: CPU Usage, .NET Object Allocation, Instrumentation, Database and Async Tools
Developer Tools PART 07

Visual Studio and Rider Profilers: CPU Usage, .NET Object Allocation, Instrumentation, Database and Async Tools

IDE profilers give the fastest results on a developer machine; Visual Studio's Database tool shows an N+1 as hundreds of short queries with the same text. On Bookstore's My Orders page we measure, by reading the same events from the command line, that lazy loading sends 80 SQL commands per request and clogs the thread pool, raise throughput 30-fold with Include and 41-fold with a projection, and place the Copilot Profiler Agent and Rider's dotTrace/dotMemory counterparts.

14 Nov 2026 11 min 3
Deep Analysis with PerfView: GC Stats, JIT Stats, Grouping/Folding and Diffing Two Traces
Developer Tools PART 06

Deep Analysis with PerfView: GC Stats, JIT Stats, Grouping/Folding and Diffing Two Traces

PerfView's power lies in GroupPats, Fold%, diffs and the GCStats/JITStats reports; since they all rest on the TraceEvent library, you can run the same analysis in code on Linux. In Bookstore we diff two traces to find that 2.6 seconds of a regression is GC waiting, measure with JITStats that ReadyToRun cuts the methods JIT-compiled at startup only from 980 to 928, and build a CI allocation gate whose noise we measured first.

14 Nov 2026 13 min 3
Hunting Memory Leaks: dotnet-gcdump, Heap Snapshot Diffing and Common Leak Patterns
Developer Tools PART 05

Hunting Memory Leaks: dotnet-gcdump, Heap Snapshot Diffing and Common Leak Patterns

A memory leak is found not with a single snapshot but with the difference between two gcdumps taken under the same load and the retention path that holds the growing object from a root. In Bookstore we catch, with dotnet-gcdump, a scoped handler that subscribes to a singleton event and never unsubscribes, taking the heap from 17.8 MB to 348.5 MB in 20,000 requests; we compare gcdump with full dumps, prove the fix with a third snapshot and list common leak patterns.

14 Nov 2026 11 min 3
Allocation and GC Analysis: gc-verbose, Allocation Sampling, the LOH and Server GC/DATAS Settings
Developer Tools PART 04

Allocation and GC Analysis: gc-verbose, Allocation Sampling, the LOH and Server GC/DATAS Settings

A GC problem shows up as frequent gen2s, a high pause share and a growing LOH; the fix is in reducing allocations, not in GC settings. In Bookstore's CSV export we tie 60 MB of allocation per request to stacks with gc-verbose and .NET 10's allocation sampling, cut it to 115 KB with streaming and ArrayPool, compare Server GC, DATAS and Workstation GC under the same load and show how the container limit sets GCHeapHardLimit.

14 Nov 2026 11 min 2
CPU Profiling: Reading Flame Graphs with dotnet-trace, Sampled Thread Time and collect-linux on Linux
Developer Tools PART 03

CPU Profiling: Reading Flame Graphs with dotnet-trace, Sampled Thread Time and collect-linux on Linux

dotnet-trace's default profile samples wall-clock time, not CPU, so waiting threads top the topN list and you find the hot spot in a flame graph by looking at request threads. In Bookstore's search endpoint we find a Regex compiled on every request in speedscope, fix it with [GeneratedRegex] and a projection, cut CPU per request from 1.87 ms to 0.07 ms, and show collect-linux's requirements with real errors.

14 Nov 2026 10 min 3
dotnet-counters and Built-in Metrics: The System.Runtime Meter, ASP.NET Core/Kestrel Metrics and Your Own Meter
Developer Tools PART 02

dotnet-counters and Built-in Metrics: The System.Runtime Meter, ASP.NET Core/Kestrel Metrics and Your Own Meter

dotnet-counters is the first-look tool: the .NET 9+ System.Runtime Meter shows GC, JIT, thread pool and CPU, and the ASP.NET Core meters show request durations with percentiles. We cover cumulative vs current metrics, the old EventCounter names in .NET 8, writing your own Meter with IMeterFactory and recording a CSV baseline with collect, under real load in Bookstore; the baseline exposes a JIT eating a third of the CPU.

14 Nov 2026 11 min 3
The .NET Diagnostics Map: Which Tool for Which Question? EventPipe, Diagnostic Ports and Safe Collection
Developer Tools PART 01

The .NET Diagnostics Map: Which Tool for Which Question? EventPipe, Diagnostic Ports and Safe Collection

Tool choice starts from the question: dotnet-counters for whether something is wrong, dotnet-trace for where time goes, dotnet-gcdump for what stays in memory, dotnet-dump for the full process state. We measure the EventPipe vs ETW vs user_events difference, the diagnostic port's TMPDIR and user rules, sidecars in containers, installing with dnx and a tool manifest, and the real overhead and file size of a trace in the Bookstore lab.

14 Nov 2026 12 min 4
DevTools and AI: Gemini AI Assistance, Chrome DevTools MCP and Recorder
Developer Tools PART 10

DevTools and AI: Gemini AI Assistance, Chrome DevTools MCP and Recorder

The Chrome DevTools MCP server opens everything in the browser to a coding agent: without a separate profile, --no-usage-statistics and --no-performance-crux, personal sessions and URLs can leave your machine. With an agent we find and fix, via source-mapped stacks, an SPA fallback returning HTML for an API call and a NaN IndexedDB key on /books/abc; Gemini AI assistance requirements, the DevToolsGenAiSettings policy, and exporting a Recorder recording to Puppeteer.

8 Nov 2026 10 min 43
Angular DevTools: Component Tree, Profiler, Injector Tree and Router Tree
Developer Tools PART 09

Angular DevTools: Component Tree, Profiler, Injector Tree and Router Tree

Angular DevTools only works on development builds, and a build made with optimization: false also behaves in development mode: the Service Worker turns off and budgets are exceeded. We read Components, the Signal Graph, the Profiler, the Injector Tree and the Router Tree with real data: fixing NG0201 with a route-level provider and seeing the new Route: reviews injector, and card template updates dropping from 855 to 0 with OnPush and track book.id.

8 Nov 2026 9 min 31
Blog Map