In any software development project so much thought goes into making the response time as low as possible. This is key to a better user experience, as most users will quickly lose interest in an app or website if the response time is slow, especially at launch. It’s very important to keep performance as a key factor during development. While a performance test can detect issues in code from developers and systems working together, it’s important to avoid major performance issues while developing each component. The most common key performance items developers should be mindful of during development are as follows:
DB Queries vs Code
Most enterprise projects involve querying data from a DB and processing the data or reacting/taking further action based on this data. As data size increases, fetching and processing this data efficiently becomes more important. For example, in a dashboard template a lot of data is fetched and processed, and typically the dashboard is frequently refreshed. It’s important that data fetched is as close as possible to what’s being displayed, otherwise a lot of processing time will be necessary after each query, which can slowly overload the system as users load the page concurrently. Developers can avoid multiple DB queries for the same data set by striking a balance between DB queries and processing in the code. For example, if a page is fetching pending cases, followed by a history for each case, it’s better to fetch both in one query instead of fetching each case and then querying the history. Otherwise, as the case list grows, the page response will slow down.
DB Indexes and Query Performance Analysis
DB indexes can be a key factor in the performance of any query and should be kept updated during the development cycle itself. In most Dev environments, the data set is not that large, so performance impact isn’t apparent, making it very easy to skip indexes. Any query should be analyzed during development to determine if a new column index is needed. Indexes reduce insert performance, so the pros and cons of adding an index should be considered in the context of the application.
Memory caching should be considered for relatively static data. This includes DB data as well as data from APIs (specifically external API’s which could be time-intensive). For example, if an API is fetching a full list of entities that are relatively static, this can be cached in memory to avoid an external call every time. Using tools like “ehcache” makes it much easier as both the API key and time to be cached can be controlled. This enables the developer to control several levels of data. For example, user data is normally static but using the tool enables the developer to control how frequently the data can be refreshed. Similarly, static reference data can be tuned to be refreshed during off-peak hours, and so on.
The developer should determine if users need to wait for a response before moving to the next activity in the chain of events. For example, if in an API call the data is stored in multiple places, or published to other systems using message queues/KAFKA, the end user doesn’t need to wait synchronously for those actions to be completed. For all such activities, async mode is more suitable, so the initiating action doesn’t need to wait for the action to be completed. Message Queues and KAFKA ensure the success of a transaction and allow users to continue without having to wait for the result (success or failure).
File Write Block Size
File activities are a common way of storing and communicating bulk data between systems. However, these activities do tend to be performance-intensive. If the project allows, the developer should write to a file in a large block as often as possible. Every write to the file queues the process for a disk-write, which has a potential to add wait to the processing, which can slow down the system. On the other hand, waiting too long to write to file can add data-loss risk in the case of a system failure, so the rollback point should be controlled based on the last write-to-file.
Poll vs. Interrupt
Several backend or frontend processes wait for an activity to happen before acting on it (e.g. receiving data from a network or a notification in an app). Wherever possible, the developer should code for an interrupt instead of polling the source to see if any data has arrived. Polling requires CPU and scheduler time; this becomes critical when user load on the system increases and several users or processes are waiting for messages to arrive. Note, however, that this may not be apparent during development.
Log messages are critical to debugging and unit testing. Several tools are available to control the log messages for any code. However, log messages are resource intensive. They require disk usage which can slow down system performance with a full system load. The developer should carefully tag all log messages with a suitable level (Info/Debug/Warning/Error) to disable Info/Debug messages in the Production environment.
Thanks for reading! We hope you found this information helpful. If you have any questions around these or any other performance factors to keep in mind during development, please don’t hesitate to reach out to us. We’d love to help you get started.