Tag.NET

Keep the gains: performance regression testing without fooling yourself

K

TL;DR: Keep only the benchmarks that protect important hot paths. Use baseline/diff comparisons to catch regressions, but do not trust noisy shared runners blindly. Performance regression testing needs stable machines, clear thresholds, and restraint. After a successful performance investigation, the benchmark folder looks valuable. It contains the history of the work: experiments, false starts, before-and-after comparisons, warmup cases, exception cases, and small probes that helped explain...

A benchmark win is not the finish line

A
Profile again: The benchmark is not the finish line

TL;DR: Once a benchmark shows a win, put the optimized code back into the profiling harness. Compare the before and after memory and CPU profiles to see whether the larger execution path benefits too. A good benchmark table feels great. The before number is slower, the after number is faster, allocations drop, and the ratio looks impressive. After hours of staring at profiler stacks and benchmark output, that table feels like the finish line. Unfortunately, the table only describes the isolated...

Turn messy production code into a useful benchmark

T

TL;DR: Useful benchmarks are controlled experiments. Copy the relevant production code, trim away unrelated work, choose realistic parameters, measure one responsibility, and use short runs for direction before spending time on full runs. Most benchmark examples look cleaner than the code we work with. Suspiciously cleaner. They compare string concatenation with StringBuilder. They call a static method. They pass one value in and return one value out. Those examples are useful for learning...

Read profiles without chasing every red bar

R

TL;DR: Profilers show cost, not priority. Start with memory, then CPU, use filters to zoom into the code path you own, and let domain context decide which hot spots deserve a benchmark. The first profile is usually disappointing. You attach the profiler, run the profiling harness, take a snapshot, and get a giant list of allocations, call stacks, framework methods, runtime methods, transport code, serializer code, and your own code hiding somewhere in the middle. The tool did its job. It showed...

Build a profiling harness before you benchmark

B

TL;DR: Before writing a benchmark, build a small profiling harness that makes the code path visible. Run it in Release mode, keep unrelated work out, add clear profiler snapshot points, and collect both memory and CPU evidence. Production code is a terrible place to start a performance investigation. There is too much happening at once. Production code is not bad; it is alive. It has real configuration and input/output, plus logging, retries, dependency injection, serialization, network calls...

Stop guessing: the performance loop for production code

S

TL;DR: A benchmark can tell you whether code got faster. It cannot tell you whether the code mattered. For that, use a loop: profile with a profiling harness, improve a hot path, benchmark and compare, profile again, then ship and observe production. The first benchmark I wrote looked deceptively easy. I needed a class, a few attributes, and a method. Then I could run BenchmarkDotNet and get a table. It looked a lot like unit testing, which made me dangerously confident. That confidence did not...

Event Sourcing: Simple is often enough

E

This is the first post in a series about event sourcing. I’ll start with a very simple event sourcing implementation that is often good enough. Most of our event streams are implemented in this simple approach. In the following posts, the concepts will be extended to match additional requirements. I’ll touch on read models, consistency, long event streams, archiving, compensation, event skipping, lifetimes, and bi-temporal event sourcing. Every post will explain the concepts and our...

Tests are Documentation, or are they?

T

Yesterday evening, I gave a workshop titled “To test, or not to test” at the Software Crafters Zürich Meetup. In the workshop, we gathered reasons to write tests: being confident that the code works, being confident that regressions can be prevented, helping to drive the implementation, and having documentation of the system. Interestingly, when I prepared the workshop, I forgot about the documentation aspect of the tests. Here is why and why it matters.

Version Conflicts with NuGet Packages

V
Packages with .net core and NuGet Logo

Yesterday, I found myself face-to-face with a rather peculiar phenomenon that managed to consume a good hour of my time. As is often the case, the solution turned out to be surprisingly simple. With the intention of documenting this for future reference (especially for my future self), I am writing this short blog post. What happened? A colleague of mine updated XUnit in our solution and merged it into our main branch. When I pulled the new code locally and tried to restore the NuGet packages...

Recent Posts