Coding for Speed - Part 1 - Measuring how fast you're going
Today I want to talk about writing code for speed. Much like writing easily laid out and readable code, writing code that can execute optimally takes a lot of hard work and is often counterintuitive to how many of us would like to code. Often we focus on the simplest way to solve a problem or the fastest/least amount of lines in which code can be written. The challenge of most optimal solution however is a lot more daunting than many of us would want to take.
Thankfully, thinking in an optimal fashion can become a matter of habit the more often it is practices and so while it will slow you down quite a lot at the start. The more you get used to thinking about efficiency coding algorithms and put tests in place to ensure you code is always at its most optimal, the faster you get at solving these challenges naturally.
Before I get into things to consider in coding for optimisation though, it is perhaps worth saying that not everything needs to work ultra-fast. Sometimes you can be working on an API or application that will only get called every few hours or so, is internal facing and doesn’t impact the dependencies of other cod. In a case such as this, often just solving the problem as simply as possible is good enough. However, the majority of work that developers will do is likely to have some impact on the overall performance of a system and so learning how to optimise your code for performance is an important skill to master.
Before I get into the code level details on things that can improve the speed of your code, I’m going to hit this topic indifferent ways. Firstly given you some approaches and thoughts to think about when measuring the performance of your software, second speak about some challenges around coding for performance and lastly, some tips to actually writing more streamlined code. I’ll cover points 2 and 3 in later articles.
Measuring your existing performance
It’s difficult to know of your coding is optimised until you have a way of actually measuring it effectively and so it’s important that we start with this.
Get the right metric
A lot of the problems covered above come from measuring the wrong things. You can often be measure server response time rather than the time it takes a web page to render, or measure performance using specific data sets without those datasets necessarily being production specific.
Making sure you’re measuring the right number is the single most important thing to do when you’re tackling a performance problem. Without that, you have no idea how much you’re helping. Similarly, don’t necessarily trust those more experienced than you to tell you the bottleneck. Make sure you evaluate it yourself.
Lots of things can affect your performance measurement. You might be a mobile developer with a slick test device that has only one program running on it. If your goal is to produce a response in < 10ms on average, that’ll be a lot easier on your test device than on your user’s four-year-old phone with low battery and a hundred apps running in the background.
It could also cause you to misunderstand your program’s characteristics. You might be I/O bound on a test device, when on most devices you’re actually CPU bound.
All sorts of external factors can affect performance including:
Network bandwidth and latency
Various caches at all layers
OS or Web Browser Versioning
When you’re measuring, try to make sure as many factors as possible are held constant so you can accurately compare different approaches. But also make an effort to understand what these factors usually look like, so you can make sure your appraisal of bottlenecks is realistic.
Measure both prod and test environments
It makes sense that you want to measure how your software is performing in production, but you should also be doing this as part of your general development cycle as well in a proper dev environment. Performance monitoring is underrated in the development space. I understand that dev environment stability is sporadic and not always production-like and that it takes a lot of effort to put the necessary monitoring tools in place, but the value in catching things quickly outweighs that in my opinion.
The biggest thing though is understand that performance between your production and development environments are likely to be different and so you need to benchmark based on those differences. And if you have multiple development environments, each one should be benchmarked. The reason for that is simple, each environment has a variety of its own environmental variables that affect performance and you want a standard baseline in which to measure against. And why development environments are less reliable, you can still get some effective measuring you performance of your code If you test it regularly and often. That way, deviations can be easily picked up and whether it is code, DB or environmental related will also be a lot easier to determine. Which brings me to last point.
Try to integrate performance tests into your build
Don’t let performance testing for something later. Include it as part of your build process, so that you can catch performance issues before they happen. In fact, you can even fail your builds if a commit causes a performance regression and prevent it going any further. If performance is important for your project, consider adding performance as part of your continuous integration. It can let you prevent performance regressions before they get shipped. The sooner you are aware of regressions, the easier they are to fix. In large code bases small regressions can build up over time unless they’re aggressively kept in check. Tests can keep them out of your system. Yes, it's difficult to run these all the time and it can slow down the pipeline a little, but honestly what takes longer, the extra few minutes to run the pipeline or the many hours of debugging to find your performance issue.
There is a saying in software development that you can only improve what you can measure. So, if you want to take your software performance seriously - you better start measuring.