Letâ€™s take a look at those three approaches to find slow code.
#1: Manual Code Inspection
First, take a high-level look at your code. Analyze the architecture of your software. Try to identify which architecture youâ€™ve used and if youâ€™ve correctly implemented it.
For example, you might have chosen event-driven architecture, but you might also be instructing a particular component through direct calls and awaiting its result. This is a serious violation of the independence of software components and how they should communicate. The goal of an event-driven system is to create an asynchronous flow of communication thatâ€™s non-blocking. But in this scenario, the chances are high that this component blocks communication.
Next, verify the implemented design patterns. Look for incorrectly used design patterns that might affect the codeâ€™s performance.
Hereâ€™s an important side note: Design patterns donâ€™t have a big impact on your code. Weâ€™re talking about a couple of nanoseconds. But often, you need design patterns to make code more readable. Improved readability is more important than these very small performance gains. Itâ€™s worth it to take a glance at design patterns to find big mistakesâ€”for example, a pattern that copies large objects while you can also pass the original object or parts of the original object.
Measure Performance to Spot Regressions
Tip: Measure your applicationâ€™s performance, even during the development phase. This allows you to keep track of the applicationâ€™s performance over time and spot regressions. Doing this can give you a good indication of which release might be problematic. Next, you can analyze the code commits for that particular release to find possible problems.
However, if you donâ€™t work with small releases, then youâ€™ll have to scan many hundreds of code commits. In the end, this is a very laborious process that requires a lot of time from your employees. Also, humans tend to make mistakes, and you might miss snippets of code that cause performance problems. Therefore, itâ€™s better to use a more structured approach to finding slow code.
A console.trace prints the call stack for a particular point in your code. This includes all functions that have been previously called, leading up to the point where youâ€™ve placed your console.trace command in the code. A call stack allows you as a developer to gain a deeper understanding of the flow of code.
In case of slow code, you might find out that a particular function is being called that shouldnâ€™t be called. However, this method tells you only the path of your code. It canâ€™t tell you which exact parts of your code are slow; youâ€™ll need more advanced tools for this kind of analysis. Still, a call stack can give you a good indication of how you can filter down the source of the slow performance.
Benefits of Tracing Using the console.trace Command
You already know that the console.trace command helps you pinpoint the exact source of the performance issue. Here are other benefits it offers:
- It allows you to easily trace your code without using any third-party tools that require setup.
- Itâ€™s easy to use, itâ€™s fast, and you can remove it quicklyâ€”all of which make it convenient.
- It prints a detailed call stack.
Next, you can use the technique of code profiling to get more details about your codeâ€™s performance.
Code profiling helps you as a developer to gain a deeper understanding of the code. Code profiling displays values (such as overall execution time), memory allocation (such as heap memory), and operating system resource usage. For Node.js specifically, a code profiling tool can also show the usage of the Node.js event loop. This is a very important element because a continuously blocked event loop can easily expose serious problems with your code.
Most often, youâ€™ll want to use a code profiling tool that doesnâ€™t require a change to the source code. On some rare occasions, youâ€™ll want to use a tool that modifies the source code to measure the performance of specific parts of your code. This latter approach is very slow, though.
In short, code profiling helps you answer questions like these:
- How many times did a method get called?
- How long does each function invocation take?
- Whatâ€™s the performance of a dependency call, such as an SQL database call or accessing Redis cache?
- How much memory is allocated, and what happens during garbage collection?
Next, letâ€™s take a look at high-level code profiling.
High-Level Code Tracing
High-level code tracing is a type of application performance monitoring (APM). When developers speak about high-level code profiling, theyâ€™re actually referring to measuring the performance of a running application. This means you have to deploy the application on a server and measure its performance.
Often, youâ€™ll have to mock up some fake users using a load testing tool that performs various operations. Also, Retrace offers a tool that helps with real user monitoring.
Moreover, an APM tool can provide you with key information, such as memory usage, garbage collection, statistics about the Node.js event loop, and CPU usage. Combining this data helps you further nail down the exact source of the performance issue.
Advantages: High-level code tracing is easy to set up. Most often, youâ€™ll have to install a tool that helps with monitoring a running application. Thatâ€™s it! Besides, high-level code profiling can give you accurate results about the performance of your code.
Next, did you know you can use low-level code tracing that involves modifying the source code? Letâ€™s explore!
Low-Level Code Tracing
Low-level code tracing makes the code up to 100 times slower. This means your code executes very slowly, of course. Thatâ€™s why you should use low-level code tracing only when you really donâ€™t know where the performance issue is located in your code.
Low-level code tracing provides very accurate measurements for specific functions in your code. However, itâ€™s a slow approach to debugging performance issues.
Use low-level code profiling only when youâ€™re unsure about the exact source of the performance issue. Low-level code profiling requires a lot of time to execute. Therefore, itâ€™s better to use high-level profiling to get a better understanding of parameters including memory allocation, CPU usage, and Node.js event loop usage.