Everyone knows that having a website which is fast is better than slow. But, did you know that improving the speed of your web application almost always comes with a trade-off?
Like Antoine Lavoisier said Nothing is lost, nothing is created, everything is transformed. What happens when altering a web or mobile app to improve its performances?
How fast do you want to be?
First of all, you should ask yourself this question. Try to target a reasonable goal, and stick to it. Maybe is your web or mobile app already fast enough? Load testing your app gives you how fast your application behaves under a given load. Is the app within the reasonable target response time?
You will reach at some point the feeling that your app is handling well for a given load. But you always would like to go further. You will have to know when to stop, because at some point, a small performance improvement comes at a huge expense.
Premature optimization is the root of all evil
From a developer point of view, software is never fast enough. We love to optimize every line of code, thinking that it will result in better overall performances. But, most developers doesn’t know that designing code with Local Optimum does not always tend to a Global Optimum.
In computer science, a local optimum of an optimization problem is a solution that is optimal (either maximal or minimal) within a neighboring set of candidate solutions. This is in contrast to a global optimum, which is the optimal solution among all possible solutions, not just those in a particular neighborhood of values.
First of all, avoid premature optimization. This is valid for every piece of software. Spending time optimizing every code path is a waste of time, and, of course, a huge waste of money. Time should be spent writing a well designed system that is easy to modify. This not only leads to a system that’s not optimized at all, but also clutters the whole software with optimized piece of code that are hard to read and to maintain.
“We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%”
Trade-off on cost
As told in Code Complete, most systems can expect a 50% performance improvement by modifying less than 5% of the code. How is this possible? Instead of spending time optimizing every piece of software, the suggested technique is to test and profile the application to spot the bottlenecks. It’s way more efficient to improve the 5% of code taking 80% of execution time. Code profiling is one way to do this at code level, load testing is another one at application level. Combining both can give impressive results.
Referring to the Amdhal’s Law, sometimes spending a great effort on the wrong piece of software leads to less overall improvement.
Improve your web application speed by testing and finding bottlenecks instead of trying to make everything fast from the ground. Rather spend money wisely on testing rather than having developers speculating about which piece of code is slow.
Trade-off on code readability and maintenability
Low level code optimization have an impact on the whole application. According to Code Complete, developers spends almost 90% reading code, and 10% time writing it. Code optimization inevitably reduces code readability because it tends to be more complex. Complex code is also less maintainable, because it requires more time to be understood. It also increases the risk of introducing bugs.
Affecting code readability affects 90% of developer efficiency.
Code should be written purposely for humans, not for machines. Trading maintainability for performance results in an immediate improvement for customers: the web application is faster. But, in the long term, it may introduce nasty bugs, difficult to find and fix, which will impact customer satisfaction too.
The system becomes cluttered with highly optimized code that is hard to read and hard to fix. It becomes a big ball of mud.
A big ball of mud is a software system that lacks a perceivable architecture. Although undesirable from a software engineering point of view, such systems are common in practice due to business pressures, developer turnover and code entropy. They have therefore been declared a design anti-pattern.
Trade off on correctness
One optimization, several bugs. Most of the time, optimizing a code path ends with multiple bugs being introduced. There is one excellent story in Code Complete.
During a meeting, developers are talking about a crappy piece of code that should be refactored.
John says: “We should not revert back to the old one, the new code is fast as hell”.
Peter then answers: “The new one is fast but it’s not working. If the requirement is not to have a program working correctly, I can design one that responds instantly.
Always think twice when asking for a speedup. If it is fast enough, do not try to make it even faster.
Test first, Improve after
Optimizing an app without testing is like walking blindfold in a minefield. Testing is knowing. But remember that testing shows the presence of defect (or performance issue) under certain conditions, but doesn’t prove their absence.