Your source of geek knowledge

Y

Latest stories

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...

A message queue bought us time

A

TL;DR: A queue can remove temporal coupling between a front end and a back end, but something still has to read the messages and run the business code behind them. That something is the message pump. Processing one message at a time protects downstream systems but increases queue wait time. Fire-and-forget processing looks faster until concurrency runs away. In practice, the pump needs an explicit limit. The medical invoicing system already worked. That made the request harder, not easier. It...

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...

Event Sourcing: the not-so-simple bi-temporal basics

E

It’s time for bi-temporal event sourcing in part eight of my event sourcing series. In this post, I’ll stick to the basics – at least I hope so. 😅 Bi-temporal event sourcing means that we have two timestamps associated with an event: The first timestamp tells us when the event entered the system, or when the system acquired the knowledge. We call this the application timestamp. The second timestamp states when the event takes effect – the effective timestamp. This is...

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...

Azure Service Bus: Earn the redesign

A
A picture explaining the earn the redesign lifecycle form the post

TL;DR: Micro-optimizations are not a substitute for design work. They are how you earn the right to redesign. In the Azure Service Bus SDK, repeated work in the Body property first led to smaller allocation fixes. Once those fixes exposed the shape of the problem, a small internal redesign made the code faster, clearer, and easier to reason about. “This code is bad. We should rewrite it.” Most developers have heard that sentence. Many have said it. I have too. The problem is not...

Recent Posts