The stance I have on code optimization is one that has been tempered by a lot of experience. Many people may disagree with it, which is fine. My set of life experiences is unique among every other human that has ever lived. Moreover, I’m pretty sure I’m right on this issue. Everything I believe on this issue can be summed up in the following sentence:
When writing code, do not think about optimization.
As a consultant, I get to help many different levels of programmers become better and more efficient at programming. I’ve been able to refine my approach through trial and error (mostly error), and I’ve been able to experiment with what changes have the greatest positive impact.
One of the mistakes I know everyone, including myself, makes when programming is to write a line of code, look at it for a few seconds, and delete it because it is “inefficient.” If I had a nickle for every time I ask someone why they wrote what they did and they answer “well, because I was worried about efficient,” I would be a very rich coder.
The kind of optimization I’m concerned about is analytical optimization. This is different from anecdotal optimization. Anecdotal optimization is where a programmer learns efficient methods and patterns through trial and error. Things like not having a
for-loop in a
for-loop in a
for-loop in a
for-loop, etc. is an example of anecdotal optimization.
Analytical optimization is the process of optimizing the least-efficient parts of a piece of software through thorough analysis. When someone says “I’ll just optimize this one like,” this is the kind of optimization they are talking about. This kind of optimization on a set of code has to be done at a different time than the writing of said set of code. Everyone knows that you can’t edit a book and write a book at the same time. The same is absolutely true of software.
When people want to prematurely optimize software, they are not thinking of the goal of optimization. This is how the conversation always goes:
- Me: Why did you write something the way you did?
- Coder: Well, I wanted it to be efficient.
- Me: What was your goal with making it more efficient?
- Coder: I wanted to write software that runs fast.
- Me: How do you know that this one line is the most inefficient part of the program?
- Coder: I don’t.
The key from that conversation is the line “most inefficient part of the program.” The goal when optimizing software is to maximize speed while minimizing the cost of making the changes. The easiest way to minimize the cost is to optimize the least-efficient part of the program. If a rational person has to choose between changing 100 lines of code to decrease run time by 1 second or 10 lines, they’ll always choose the latter.
For it to be successful, the process of optimizing software needs to be well defined, controlled, and analyzed. The following is the pattern I use during the optimization process.
First, find the least efficient part of the program. For a web application, this is best done by opening up Dev Tools, recording your activity, and purposefully doing things that you know are slow. Once you’ve run through the path that you have a guess is inefficient, go to the Network tab and sort by Response Time descending. The thing that took the most time to respond needs to be the first thing you focus on.
Second, look closely at the longest Response Time request. This is usually an AJAX request. See if you can execute the AJAX request outside of your system. Postman is a great tool for this so you can execute just that request. Run the request several times and look at the response time. If it remains high and constant, you have your first target.
Third, add code to the code run by the AJAX request to output the start/end time in milliseconds. When dealing with a language like PHP, this can be done with something like the following, assuming my changes start after the opening PHP tags.
var_dump("-------------Start of the program-----------");
// Some other stuff runs that actually does the work
var_dump("-------------End of the program-------------");
Run the request again, and look at the response for the timing information that was output. The difference between the end and start of program times should be equal to the response time your browser sees. That means that all of the things between those statements are taking most of the time.
Fourth, add output start/end time for the relevant sections of the current code. If your script has a
switch statement to determine what function to call based on the request, then adding a start/end
microtime() call right after the case/before the break works best. If you have some complicated
else statements, then putting them between the braces works best. There is no silver bullet when it comes to picking where to add this data. The only thing that matters is that you capture all possible cases, you output unique strings before the time to ensure you can determine where it came from, and that you focus on large chunks of code rather than granular sections.
Fifth, once the least efficient section of code is determined, repeat the fourth step again. What will often happen is that one section will take a disproportionate amount of time during the response. That is the section that you want to focus your attention on. Even if all of the other sections were tuned to the nth degree, the inefficiency of that one section will pull everything else in the response down. That is why it is so important to focus in on the worst performer.
Sixth, repeat the process until a section can be obtained that is small and extremely inefficient. By continually narrowing focus, you make sure that you are only spending the cost (your time) on the most needed area. Getting continual, objective feedback through timestamps is the best way I know of to identify this area. Spreadsheets often help me keep track of which areas I’ve dived into, and are good ways to do the computation of the difference between the start and end times.
Seventh, celebrate because you just practiced analytical optimization.
Optimizing code is one of the most difficult but rewarding tasks we programmers have. If I have to choose between spending a day hunting down a bug due to a rare race condition or speeding up an entire application by 5%, I’ll choose the optimization any day. It can become tedious, but seeing the increase in positive feedback from end users makes it all worth it.
The post Optimizing Code appeared first on Zach Gardner's Blog.