Over the years I have used a concoction of strategies to improve performance of software applications. I thought it would be useful to list the most common ones as a starting point, for someone trying to improve the performance of their application.
Please be mindful that I am coming from an experience of web and server applications where data is at center stage, and scanning or retrieving data efficiently and quickly is the core challenge. However, I do believe that some of these strategies can be used to improve performance of non-data centric software as well.
Profiling the application
At its core performance improvement work revolves around profiling your application for speed and resource usage and trying to improve that. Its a common misconception that profiling involves using expensive and or complicated software tools and systems that require a great deal of effort to setup and use, and generally have a very steep learning curve.
While this is may not be completely untrue, more often than not simple start to end time reporting in code, recoding memory usage at different stages of your execution, using tools like Apache Bench or unix
time command on the terminal is all you need to get going.
Use profiling to benchmark your system for current performance and establish your baseline numbers. This is very important if you were to eventually improve. Without the baseline you wont know if the changes you are incorporated are helping or making the situation worse.
Start with reading and understanding the code
Before you sign up for New Relic or pay for the professional version of Visual Studio I should mention that in my experience, reading and analyzing your code happen to yield a lot of good insights and solutions. Also remember that instrumented code may not even show the performance problem you were trying to dissect. Take time to think about your problem before jumping in.
Replace multiple fetches with a single multi-get
I’m surprised that how many times we forget or avoid to use the multiple-get function of the same method just because it could be a bit more complicated to use. Whether you are dealing with file IO or remote data sources, fetching stuff multiple times adds a lot of overhead, doing a bulk fetch can improve this drastically.
Backgrounding, multi-threading and Asynchronous IO
I’ve combined these techniques into one section, the general idea is similar; any processing that can be done in the background while you perform other tasks, or starting multiple background tasks in parallel and waiting for them to finish is always faster than doing them one by one.
Cache data at the application level
In other words, don’t fetch it twice in your code. Anything fetched from disk or remote source should be saved to an application level key-value store, which may just be a simple global array with accessors. I won’t be surprised here if using a global variable irks you the wrong way. Personally, I completely condone it when used judicially with wrapper accessors.
The following example shows one possible implementation
Caching data at the machine/server level
This technique is extremely useful when dealing with data that does not exist on the same machine where you application is running. Any modern clustered environment can benefit from it. This could be as simple as using a local cache file or something similar to
APC in PHP application.
Use an external cache to reduce data store access
In this strategy an external memory store like
Redis is utilized to hold data so you don’t have to fetch it again from your database or storage. This is often referred to as the
Cache Aside Design Pattern
Improve Query performance
When using relational databases query performance analysis is relatively a straight forward thing. Most RDBs provide ways to do it. Fortunately there are old established ways of doing business here and some cases creating and using the right indexes is all thats needed.
For non-relational databases managing and creating your own indexes where you can fetch the relevant data directly using a key is much faster when compared with a scan query.
Improve network performance by using compression
When accessing data over the network, whether its a client accessing your web server or you accessing a database, network congestion could be a major contributor to latency. Server web and data server provide built-in data compression features.
Improve network performance by using faster protocols
When communicating between two servers, for example in the cases of micro-services where a single server does not implement all functionality, using binary or compact techniques, for example
Protocol Buffers or
Apache Thrift could significantly improve performance.
Utilize Content Delivery Networks (CDN)
For geographically diverse deployments you may use CDNs not just a way to way to improve content delivery but it can potentially improve API calls, just make sure to query parameters to differentiate between requests.
I purposely did not mention switching languages, frameworks or platforms but rest assured that I am cognizant of the fact that sometime that is what is really needed. Let me know in the comments if I missed a particular strategy that worked for you.