Perspective

More than Just Design: Significantly Boost Performance with Code Optimizations

When it comes to technology, we are not particularly patient. A snappy user experience beats a glamorous one. We engage more with a site when we can move freely and focus on the content, instead of an endless wait. User Experience research recommends the following responsiveness guidelines:

  • Delays <0.1 seconds feel instantaneous.
  • Delays < 1 second are the limit for a user’s flow of thought to stay uninterrupted. The user will notice the delay but still be able to focus on the task at hand.
  • Delays between 2 to 10 seconds should have a spinning icon to visually indicate something is happening.
  • Delays > 10 seconds should have a percent-done indicator along with a cancel button.

Just to put these requirements in context, it takes between 0.1 and 0.4 seconds to blink. It takes six seconds to breathe. With these kinds of demands, if you don’t design with performance in mind, nobody will use the product. But performance isn’t as simple as you might think.

Why Design Is Critical in a World Where Not All Operations Are Created Equal

To deliver the functionality of an application, many different types of tasks need to be performed: reading data from a database, performing calculations, security checks and rendering User Interface (UI) components. From the perspective of performance, not all operations are created equal. Operations performed in memory are orders-of-magnitude faster than operations that require calls over the network.

For example, it takes 20 milliseconds to read 1 MB sequentially from a disk, whereas it only takes 250 microseconds to read 1 MB sequentially from memory.

When starting the design for your application, you will want to consider the most critical parts and come up with an architecture that is appropriate for the problem at hand. You will need to start with objective goals.

  1. How long should an average request take?
  2. How many concurrent users should the application support?
  3. What is the peak load the application must handle?
  4. What is the deployment environment for the application?

Think of it this way: If you’re using a hacksaw to clear-cut a forest, you are going to have a bad day. If you don’t have the right tools for the job, no amount of heroics is going to help.

Using a layered design will make identifying and correcting performance problems much simpler. There are many potential reasons for a sluggish application. Having multiple types of operations occurring within the same chunk of code can obfuscate which chunks are slow and why. It also makes it more difficult to optimize without breaking unrelated code.

How to Use Code Optimizations Effectively to Maximize Performance

Code optimizations change already-correct code so that it executes faster. To do it effectively, first define your optimization goals clearly and measure the impact of the changes you make using a profiling tool. Do not start performing optimizations without a profiling tool of some sort. Performance problems are often not obvious, and the changes you introduce to the code base could very well make it perform worse!

Before you optimize, you’ll want to make sure the code works. Then you’ll want to refactor it to make it right and easy to understand. Only then should you optimize it.

Code optimization looks different depending on the type of operation.

  1. For I/O-bound operations, you will want to first identify the costly operations during application profiling. This might include disk reads, web service calls or database calls. Once identified, you might consider rewriting the slow parts using either multithreading or batching:
    • Multithreading executes multiple threads simultaneously. If you multi-thread code, break the task into individual pieces that don’t require communication and locking. Race conditions and deadlocks are very difficult to identify and fix.
    • Batching updates the interface to perform a batch of work instead of making multiple network calls. By batching work, you limit the number of expensive network calls that are made.
  2. For CPU-bound optimizations, know your algorithms and data structures. Restructure your applications to use the most appropriate structure. For example, if you need to determine the intersection of two lists in memory, a hashset will be much faster than a list. The complexity class for performing a lookup is O(1) for a hashset instead of O(N) for a list. Comparing two lists with 100,000 items, that is a difference between 100,000 and 10 billion operations.

If you want to produce a product people will use, performance must be at the front of your mind. Ultimately, if the application design is faulty, code optimizations probably couldn’t save the application at the last minute. But once the design is right, code optimizations can be used to identify and remove the hot path within the application to really set your application apart.

At Daugherty, our Dev Center contains software engineers who have been involved in all aspects of delivering high-quality software: from requirements analysis to deployment automation. If you’re a developer ready to work for many different brand-name clients, developing and delivering pragmatic solutions to their business needs, join our team today.

Ready to differentiate your organization?

Contact Daugherty
Back to Top Button