Software Performance
You start a project, it gets traction, people start using it, some of these people start complaining that it is too damn slow. You realize that they are right. This blog post is about what you do next.
We will identify a change on the backend with [backend] and on the mobile/web app as [frontend]. We will also use an imaginary photo app to illustrate some examples.
- [backend] Batching
This is also know as the N + 1 problem. In summary, instead of doing Photo.find(id1), Photo.find(id2), Photo.find(id3), etc…turn them into one round trip request to your data store with Photo.where(id1, id2, id3).
2. [backend] Paging
Instead of spending a lot of time on the network returning all your content in one single page and have the backend and frontend block and struggle with a very large amount of content, split the problem into smaller parts and introduce paging.
3. [backend] Background Jobs
You shouldn’t be doing this in either case but if you are, addressing this would provide major improvements. If you are sending emails, push notifications, anything that don’t need to be done part of the request/response flow and could be done later, consider doing them in a background job and free the resources on your server to handle the incoming requests.
4. [backend] Caching and Denormalizing
Instead of going to your data store or instead of regenerating a response dynamically every single time, consider adding a cache and service your response from the cache instead of the data store or the dynamic content. Additionally, denormalize things and move as much processing from the read/request to the write/data creation time. This will mean your data is stored in two places but that’s usually okay and is the price to pay to avoid normalizing and fetching data during the request time.
5. [frontend] Caching
Store a version of the content on the mobile and load the app with this cached content. Send a request to the backend with an eTag where the backend can reply with either a simple “Not Modified” or return back a set of new or updated content.
6. [frontend] Loading Spinner
Simple change, major ROI. It does not fix the underlying performance problems but it increases the “Perceived Performance” and sometimes this is enough
7. [frontend] Prefetching
Anticipate user actions and prefetch any content that’s likely to be consumed next. This works really well with paging as we can prefetch the next page while the user is consuming the current page.
Performance is an endless topic and we can easily start addressing other areas like network performance (CDNs), performance analytics and baselining, tooling and profiling, etc… In the end, there’s no silver bullet in terms of performance improvements and this list will keep growing and needs to be fine tuned to your specific issues. We are more and more in an era where writing software means writing responsive software and this is usually a process of continuous improvement more than anything else.
