Web

The role and usage of the perf_fooks module in Node.js

Published Time : 2025-11-28

Node.js is an open-source, cross platform JavaScript runtime environment that allows developers to run JavaScript code on the server-side. Node.js is built on the Chrome V8 engine and designed specifically for high-performance, high concurrency network applications. It is widely used in building server-side applications, network applications, command-line tools, and more.

This series will be divided into 9 articles to introduce the principles of Node. js technology: from analyzing the debugging capabilities of Node. js to how to add a built-in module in Node. js, from the usage of performance analysis tool perf_fooks to the analysis of performance issues in Chrome VNet, to understanding ABI stability, exploring JavaScript runtime based on V8 encapsulation, module loading methods, external built-in modules, and a comprehensive interpretation of Node. js addon. Each article is full of practical knowledge.

In the previous section, we discussed how to add a built-in module in Node.js. In this section, we mainly share the role and usage of the perf_0oks module in Node.js. This article is the third in this series, created by the experience technology team, Qu Jinxiong. The following is the main content of the text.

Preface

How to measure the time consumption of a piece of code in Node.js?

For example, the time it takes to iterate 100 times in a for loop. Let's start the explanation of this article with this question in mind.

1. Use Date. now()

It's easy to think of taking a time before and after the loop, and then subtracting it


After running multiple times, it was found that the result is always 0. The reason is that Date. now() can only be accurate to the millisecond level and cannot be used to calculate time consumption such as a few tenths of a millisecond.

2. Use console. time() and console. timeEnd()


Run the above code and print on the console: example: 0.179ms. The goal is achieved, but this method is only applicable for printing results on the console. If you want to put it in the log, it won't work.

3. Use some third-party libraries

Of course, such third-party libraries do exist, such as the benchmarked. js library, which can also provide high-precision timestamps. But the problem is that these libraries are third-party, and if the code of Node.js itself needs to be tested or performance data recorded, the third-party libraries will no longer be available.

Before the appearance of the perf_fooks module in this article, there were more solutions adopted, which will not be listed here. In short, we need Node.js's own modules. In 2017, when the Node 8.5 version was released, there was already a perf_fooks module to provide high-precision timestamps and test code time.

Next, let's explore the usage of this module. Due to the fact that the official documentation for Node is always concise and rarely includes' why ', it is like a dictionary. We habitually searched the entire internet for beginner tutorials provided by kind-hearted people, but this time we failed due to the lack of documentation on perf'hooks. Helplessly, return to the official document.

Believe it or not, as beginners like me, there are a hundred thousand reasons why you want to ask

Why is it different from what I imagined when used?

Why do we need a new Performance Observer?

What does Performance Observer do?

At this point, we have only one last resort, gnawing on the source code. The process and difficulties involved are not mentioned, only the conclusions drawn from the source code. The solution to the initial problem will be included in the explanatory examples.

The Node.js source code used in this article is 18.20.2.

Operating principle

Before we talk about the operating principles, we need to understand three basic concepts. Just like before we learn a programming language, it doesn't matter if we can write code or not. We have to familiarize ourselves with variables, functions, classes, and objects first before we can learn statements, APIs, and so on.

Explanation of Operating Principles

Once you understand the first two basic concepts, the operating principles will be easy to explain. You can brainstorm it yourself. There is an array in memory called Performance Timeline, which is used to store performance data in chronological order.

So, next, implementing the ability to write and read to the timeline array separately can basically meet the requirements of this performance module. The specific implementation will be discussed in later chapters.

Write data to the timeline

The literal translation of perf_ books is performance hook. In fact, 'hook' is more accurately translated as' hook '. One end of the hook is fixed on the software system, and as for what to hang on the hook, it is decided by the user. In short, the hanging thing (code) will be executed, and the capital punishment timing is determined by the system. What exactly do hooks refer to in the perf-hooks system?

Performance Entry data is divided into several types such as node, mark, measure, gc, function, http, and http2. Continuing the hook mentioned earlier, writing data to the timeline actually involves placing the hook on the node system. Except for mark and measure, several other types of hooks have been pre installed (built-in).

The functions corresponding to mark and measure are encapsulated hooks (including hook functions and defined function contents), which can be used together to measure the time difference between the capital punishment of two specified hooks. This time difference can be called a custom metric. Specifically, the mark hook (performance. mark) is used to collect performance data such as capital punishment time at a specified code location, while the measure hook (performance. measure) is used to calculate the time difference between two hooks.

Simply put, when performance.mark ('A ') is executed, it creates an entry of type PerformeMark (also a subclass of PerformeEntry) and writes it into the timeline; When performance. measure ('A ') is executed, a Performance Measure (also a subclass of Performance Entry) type entry is created and written into the timeline.

Retrieve data from the timeline

There are two ways to query data from a timeline: synchronous and asynchronous. To avoid the impact of querying timeline data code itself on performance, the recommended method is usually asynchronous.

Synchronization method query

The following three methods are used to synchronously query performance data from the timeline, returning the complete timeline data or a subset of it.

performance.getEntries()

performance.getEntriesByName(name[, type])

performance.getEntriesByType(type)

In the following two examples, the query code is executed synchronously, and if there is too much performance data on the timeline, the query action will significantly block the main thread.

API walkthrough

Understanding the Performance Timeline is the key to the design philosophy of this module. In addition to defining performance data structures, it is also an API for reading and writing data to the timeline. Once you understand this layer, the entire module can be considered almost understood.

Summary and Review

The inference in the text is that the timeline is a global variable, which is actually inaccurate. The accurate composition and automatic clearing mechanism of the timeline are questionable. But this understanding can help us quickly establish a basic understanding of the perf_fooks module.

In the next section, we will share the analysis of Node.js performance issues using Chrome VNet. Please stay tuned for this series. After learning this series, you will gain:

Enhance debugging and performance optimization capabilities

Deeply understand modularization and extension mechanisms

Explore underlying technologies and customization capabilities