chapter ten

10 Performance and profiling

 

This chapter covers

  • Why performance testing is important
  • Benchmarking code with BenchmarkDotNet
  • Collecting profiles with BenchmarkDotNet
  • Analyzing profiles with tools
  • Understanding the garbage collector
  • Writing web API tests with NBomber

10.1 Why performance test?

Premature optimization is the root of all evil.

-- Sir C. Antony R. Hoare

This quote by Sir Tony Hoare, popularized by Donald Knuth, is perhaps the most misunderstood guidance for writing applications that perform well. Optimizations, in this context, refer to CPU cycle counting and tuning low-level operations. Programmers love to do these things, but they can often get lost in the minutiae and miss the big picture. Sir Tony wasn’t trying to tell us to forgo considering performance when designing our applications. He was warning us against getting mired down in optimizing the wrong things.

Performance considerations need to start at the design phase, i.e. at the macro level. It requires understanding the components involved and how they perform under load. For some components, like Kafka, RabbitMQ, CosmosDB, etc., it’s easy to find benchmarks and blog posts covering optimizations so you can get a general sense of how well the component will perform. Other components, like relational databases, will greatly depend on how they are used (e.g. complexity of schema and queries).

10.2 Introduction to BenchmarkDotNet

10.3 Profiles

10.3.1 Capturing profiles with BenchmarkDotNet

10.3.2 Analyzing profiles

10.3.3 PerfView

10.3.4 Understanding garbage collection

10.4 Web performance testing

10.5 Summary