perf hooks

Performance Measurement APIs

1. High-Resolution Time

Imagine you have a stopwatch that can measure time down to the billionths of a second. That's what the High-Resolution Time API does for JavaScript! It lets you measure time very accurately for benchmarking code or tracking performance issues.

2. Performance Timeline

Think of this API as a timeline where you can mark and measure events that happen in your JavaScript code. So, you can record when a function starts and ends, for example, and compare the performance of different code paths.

3. User Timing

This API allows you to log events that are experienced by the user, such as how long it takes for a page to fully load, or the time spent on a specific section of the page. It helps in optimizing the user experience and making sure your web pages are performing as fast as possible.

4. Resource Timing

This API tracks the timing of resources that your web pages use, such as images, scripts, and CSS files. By monitoring the performance of these resources, you can identify any bottlenecks and improve the overall loading speed of your pages.

Code Example

Here's a simple code snippet that shows how to use the Performance Timeline API:

const { PerformanceObserver, performance } = require("perf_hooks");

const observer = new PerformanceObserver((items) => {
  console.log(items.getEntries()[0].duration);
  performance.clearMarks();
});

observer.observe({ entryTypes: ["measure"] });

performance.mark("Start");
performance.measure("Start to Now", "Start");

// Do some time-consuming tasks...

performance.mark("End");
performance.measure("Start to End", "Start", "End");

This code creates a performance observer that logs the duration of specified performance measures. Here's what it does:

  • Creates a PerformanceObserver instance and observes the measurement events.

  • Marks a timestamp named 'Start' using performance.mark().

  • Measures the time from 'Start' to the current time using performance.measure(), giving it a name "Start to Now".

  • The observer logs the duration of the "Start to Now" measure when it finishes.

  • After some time-consuming tasks, it marks another timestamp called 'End' and measures the time from 'Start' to 'End'.

  • The observer logs the duration of the "Start to End" measure when it finishes.

Real-World Applications

  • Performance benchmarking: Measure the performance of different algorithms or code optimizations.

  • Application profiling: Track the time spent in different parts of your application to identify performance bottlenecks.

  • User experience optimization: Monitor how users interact with your web pages to improve loading times and page responsiveness.

  • Resource optimization: Identify and fix slow-loading resources to improve overall website performance.


Node.js Performance Metrics

perf_hooks.performance

perf_hooks.performance is a built-in feature in Node.js that allows developers to measure the performance of their programs. It provides a time-stamping functionality similar to the window.performance object in web browsers.

How it Works

perf_hooks.performance has a built-in timestamp that starts when the Node.js instance is initialized. It can be used to measure the duration of specific tasks or operations in your code.

Usage

To use perf_hooks.performance, import the perf_hooks module and then use the performance property:

const { performance } = require("perf_hooks");

Example: Measuring the Execution Time of a Function

// Start the timer
const start = performance.now();

// Run the function you want to measure
const result = myFunction();

// Stop the timer
const end = performance.now();

// Calculate the duration
const duration = end - start;

console.log(`Function execution time: ${duration} milliseconds`);

Applications

perf_hooks.performance can be used in various real-world applications:

  • Performance Monitoring: Measuring the overall performance of your Node.js application.

  • Code Optimization: Identifying bottlenecks and optimizing code to improve performance.

  • Debugging: Troubleshooting performance issues by tracking the time taken by different parts of your program.

  • Profiling: Collecting data on the execution time and resource consumption of your code.

  • Benchmarking: Comparing the performance of different algorithms or code implementations.

Additional Features

In addition to the timestamp functionality, perf_hooks.performance also provides:

  • Timer Resolution: You can adjust the resolution of the timestamp (in milliseconds) using performance.timeOrigin.

  • Memory Usage: You can retrieve memory usage data using performance.memoryUsage().

  • Node.js Native Modules: It can be used to measure the performance of Node.js native modules (addons).


Performance.clearMarks() Method

The performance.clearMarks() method lets you remove performance marks from the browser's timeline. Performance marks are like bookmarks in time that you can create to track when certain events happen, such as when a page loads or when a user clicks a button.

Parameters:

  • name (optional): The name of the performance mark you want to remove. If you don't provide a name, all marks on the timeline will be removed.

Usage:

// Remove a specific performance mark
performance.clearMarks("myMark");

// Remove all performance marks
performance.clearMarks();

Real-World Application:

Performance marks can be useful for performance profiling, such as identifying bottlenecks in your code. By clearing performance marks, you can start fresh with a clean timeline, making it easier to analyze performance data.


performance.clearMeasures([name])

Description

The performance.clearMeasures([name]) method removes PerformanceMeasure objects from the Performance Timeline.

Parameters

  • name (optional): The name of the measure to remove. If not provided, all measures will be removed.

Return value

Nothing.

Example

const { performance } = require("perf_hooks");

// Create a measure
const measure = performance.mark("measure-name");

// Clear the measure
performance.clearMeasures("measure-name");

// Check if the measure has been cleared
console.log(performance.getEntriesByName("measure-name").length === 0); // true

Real-world applications

  • Measuring the performance of a specific task

  • Tracking the time it takes for a user to complete a task

  • Identifying bottlenecks in a system


What is performance.clearResourceTimings()?

performance.clearResourceTimings() is a method in Node.js that allows you to remove performance resource timing data from the Resource Timeline. Performance resource timing data includes information about the loading and execution of external resources, such as images, scripts, and CSS files.

How to use performance.clearResourceTimings()

To use performance.clearResourceTimings(), you simply call the method without any arguments. This will remove all performance resource timing data from the Resource Timeline.

performance.clearResourceTimings();

If you want to remove only specific performance resource timing data, you can pass the name of the resource to the method.

performance.clearResourceTimings("my-resource-name");

Why would you use performance.clearResourceTimings()?

You might use performance.clearResourceTimings() if you are testing the performance of your application and want to clear out any old performance resource timing data. This can help you get more accurate performance measurements.

Real-world example

Here is an example of how you might use performance.clearResourceTimings() in a real-world application:

// Run a performance test
const results = performance.getEntries();

// Clear the performance resource timing data
performance.clearResourceTimings();

// Run the performance test again
const newResults = performance.getEntries();

// Compare the two results to see how the performance has changed

Potential applications

performance.clearResourceTimings() can be used in a variety of applications, including:

  • Performance testing

  • Debugging performance issues

  • Optimizing the performance of your application


Event Loop Utilization

The event loop is a fundamental part of Node.js. It's responsible for handling asynchronous events, such as callbacks, timeouts, and file I/O. The event loop utilization (ELU) is a measure of how busy the event loop is. A high ELU means that the event loop is spending a lot of time processing events, while a low ELU means that the event loop is idle.

You can use the performance.eventLoopUtilization() method to get the ELU. The method returns an object with the following properties:

  • idle: The amount of time (in milliseconds) that the event loop was idle.

  • active: The amount of time (in milliseconds) that the event loop was active.

  • utilization: The ELU, which is the percentage of time that the event loop was active.

Here's an example of how to use the performance.eventLoopUtilization() method:

const { performance } = require("perf_hooks");

const elu = performance.eventLoopUtilization();

console.log(`ELU: ${elu.utilization}%`);

The output of the above code will be something like the following:

ELU: 50%

This means that the event loop was active 50% of the time during the last second.

Potential Applications

The ELU can be used for a variety of purposes, including:

  • Debugging performance issues. A high ELU can indicate that the event loop is overloaded and that the application is not performing optimally.

  • Optimizing code. By understanding how the ELU changes in response to different code changes, you can optimize your code to reduce the ELU and improve performance.

  • Monitoring applications. The ELU can be used to monitor the performance of applications over time. This can help you identify trends and potential performance issues.

Here's an example of how the ELU can be used to debug a performance issue:

const { performance } = require("perf_hooks");

// Create a function that takes a long time to run
function longRunningFunction() {
  for (let i = 0; i < 1000000000; i++) {
    // Do something that takes a long time
  }
}

// Call the function and measure the ELU
const eluBefore = performance.eventLoopUtilization();
longRunningFunction();
const eluAfter = performance.eventLoopUtilization();

// Calculate the difference in ELU
const eluDelta = eluAfter.utilization - eluBefore.utilization;

console.log(`ELU difference: ${eluDelta}%`);

The output of the above code will be something like the following:

ELU difference: 50%

This means that the longRunningFunction() function caused the ELU to increase by 50%. This indicates that the function is taking up a significant amount of time and that it may be a performance bottleneck.

By understanding how the ELU changes in response to different code changes, you can optimize your code to reduce the ELU and improve performance.


performance.getEntries()

  • What it does: Returns a list of PerformanceEntry objects in chronological order with respect to performanceEntry.startTime.

  • What does it return: An array of PerformanceEntry objects.

  • How to use it: Use the getEntries() method on the performance object to get a list of performance entries.

const entries = performance.getEntries();
for (const entry of entries) {
  console.log(entry.name);
}

This will log the name of each performance entry to the console.

Real-world applications

  • Performance analysis: You can use the getEntries() method to analyze the performance of your web application. For example, you can use it to identify bottlenecks in your code or to compare the performance of different versions of your application.

  • Debugging: Performance entries can be helpful in debugging performance issues in your web application. For example, you can use them to identify slow network requests or long-running scripts.


Simplified Explanation:

Imagine you're running a race. You want to know how long it takes different parts of the race to complete.

The performance.getEntriesByName() function lets you do this by tracking the "names" of different parts of the race and the time it takes for each part to start.

Parameters:

  • name: The name of the part of the race you want to track (e.g., "Lap 1").

  • type (optional): The type of race event you want to track (e.g., "start").

Return Value:

A list of entries that show the start time and other details for each part of the race that matches the given name and type.

Real-World Example:

You're building a website that loads data from a server. You want to measure the time it takes to load different parts of the website, such as the header, sidebar, and content.

You can use performance.getEntriesByName() to track the start time of each part of the website:

// Track the start time of the header
performance.mark("header-start");

// Track the start time of the sidebar
performance.mark("sidebar-start");

// Track the start time of the content
performance.mark("content-start");

// Get the performance entries for each part of the website
const headerEntries = performance.getEntriesByName("header-start");
const sidebarEntries = performance.getEntriesByName("sidebar-start");
const contentEntries = performance.getEntriesByName("content-start");

This gives you a list of entries that you can use to calculate the time it takes for each part of the website to load.

Applications:

  • Measuring the performance of web applications

  • Profiling and optimizing code

  • Identifying bottlenecks and performance issues


Simplified Explanation of performance.getEntriesByType(type) Method

Purpose:

This method returns an array of performance entries of a specific type.

Parameters:

  • type: The type of performance entries to retrieve. Possible values are:

    • "resource": Entries related to loading resources (e.g., images, scripts)

    • "mark": User-defined performance marks

    • "measure": User-defined performance measurements

    • "navigation": Navigation-related entries (e.g., page load, unload)

Return Value:

An array of PerformanceEntry objects.

How it Works:

You can use this method to retrieve specific types of performance entries from the browser's performance timeline.

Example:

// Get all resource loading performance entries
const resourceEntries = performance.getEntriesByType("resource");

// Loop through the entries and print their start times
for (const entry of resourceEntries) {
  console.log(entry.startTime);
}

Applications:

  • Analyzing page load performance

  • Identifying slow-loading resources

  • Tracking user interactions

  • Profiling code execution


performance.mark(name[, options])

  • name {string} - A name for the mark.

  • options {Object}

    • detail {any} - Additional optional detail to include with the mark.

    • startTime {number} - An optional timestamp to be used as the mark time. Default: performance.now().

Creates a performance marks in the browser timeline

Performance marks are used to mark specific events or points of interest in the browser timeline. This can be useful for tracking performance metrics or understanding how code is executing.

For example, you could create a mark to indicate when a function starts or ends, or when a particular DOM event fires. Then, you can use the performance.getEntries() method to retrieve the performance entries for a given time range, and see how long the function took to execute or when the DOM event fired.

Syntax

performance.mark(name[, options]);

Here is an example of how to use the performance.mark() method:

// Create a mark named "my-mark"
performance.mark("my-mark");

// Get the performance entries for the "my-mark" mark
const entries = performance.getEntriesByName("my-mark");

// Log the performance entry
console.log(entries[0]);

Output:

PerformanceEntry {
  entryType: "mark",
  name: "my-mark",
  startTime: 1625410179641.988,
  duration: 0
}

Real-world applications

Performance marks can be used for a variety of applications, including:

  • Tracking the performance of specific functions or code blocks

  • Identifying bottlenecks in your code

  • Understanding how users interact with your website or application

  • Optimizing the performance of your website or application

Potential applications

Tracking the performance of specific functions or code blocks

You can use performance marks to track the performance of specific functions or code blocks. This can be helpful for identifying bottlenecks in your code or understanding how long a particular function takes to execute.

For example, you could create a mark at the beginning and end of a function, and then use the performance.getEntries() method to retrieve the performance entries for the function. This would give you the start and end time of the function, as well as the total duration of the function call.

Identifying bottlenecks in your code

Performance marks can also be used to identify bottlenecks in your code. By creating marks at key points in your code, you can see how long each section of your code takes to execute. This can help you identify areas where your code could be optimized.

For example, you could create a mark at the beginning and end of a loop, and then use the performance.getEntries() method to retrieve the performance entries for the loop. This would give you the start and end time of the loop, as well as the total duration of the loop.

Understanding how users interact with your website or application

Performance marks can also be used to understand how users interact with your website or application. By creating marks at key points in your user interface, you can see how long users spend on each page, and which pages they visit most frequently. This information can help you improve the user experience of your website or application.

For example, you could create a mark when a user clicks on a button, and then use the performance.getEntries() method to retrieve the performance entries for the button click. This would give you the time that the user clicked on the button, as well as the total duration of the button click.


Performance.markResourceTiming()

Purpose: Records a performance mark for a specific resource request.

Parameters:

  • timingInfo: An object containing performance timing information.

  • requestedUrl: The URL of the requested resource.

  • initiatorType: The type of initiator that triggered the request, such as "fetch" or "script".

  • global: (Optional) An object to which the new PerformanceResourceTiming entry will be added.

  • cacheMode: (Optional) The cache mode used for the request, either "" (no cache) or "local" (cached locally).

Usage:

const { performance } = require("perf_hooks");

performance.markResourceTiming(
  {
    connectEnd: 100,
    connectStart: 50,
    domainLookupEnd: 100,
    domainLookupStart: 50,
    fetchEnd: 400,
    fetchStart: 200,
    redirectEnd: 0,
    redirectStart: 0,
    responseEnd: 300,
    responseStart: 200,
  },
  "https://example.com/script.js",
  "script"
);

Explanation:

  • The markResourceTiming() method creates a new entry in the performance timeline with the specified timing information for the given URL.

  • This allows you to record the performance metrics for specific resource requests, such as how long it took to connect to the server, perform DNS lookups, fetch the resource, and receive the response.

  • The initiatorType parameter helps identify the type of action that triggered the request, making it easier to trace the cause of performance issues.

  • The global parameter allows you to specify an object to which the new entry will be added. If omitted, the entry will be added to the global performance timeline.

  • The cacheMode parameter indicates whether the resource was served from the local cache or not.

Potential Applications:

  • Performance Monitoring: Track the performance of specific resources, such as scripts, images, and CSS files, to identify bottlenecks and optimize performance.

  • Troubleshooting: Isolate performance issues by pinpointing the exact timing information for resource requests that are causing delays.

  • Web Page Analysis: Analyze the performance of web pages by collecting data on resource timings and identifying opportunities for improvement.


Performance Measurement

Imagine you're timing how long it takes to bake a cake. You start the timer when you put the cake in the oven and stop it when it's done. The elapsed time is the "duration" of baking the cake.

In Node.js, you can do something similar to measure the duration of code execution. You use the performance module.

Creating a Performance Measure

To create a performance measure, you use the performance.measure function:

const name = "My Measure"; // Unique name for the measure
const startMark = "my-start-mark"; // Mark the start of the measurement
const endMark = "my-end-mark"; // Mark the end of the measurement

performance.measure(name, startMark, endMark);

This creates a new "My Measure" in the Performance Timeline. The Timeline is like a history of all the performance measurements you've made.

Getting Performance Measures

Once you have created a measure, you can get it by name using the performance.getEntriesByName function:

const measures = performance.getEntriesByName("My Measure");

This will return an array of all the performance measures with the name "My Measure".

Example: Measuring Server Response Time

Let's say you want to measure how long it takes for your server to respond to a request. You can use the following code:

const startTime = performance.now(); // Get the start time
// Make the server request
const endTime = performance.now(); // Get the end time

const measureName = "Server Response Time";
performance.measure(measureName, startTime, endTime);

After the request is made and the response is received, you can get the duration of the server response using the code above.

Potential Applications

Performance measurement is useful for:

  • Optimizing code performance

  • Troubleshooting performance issues

  • Identifying performance bottlenecks


performance.nodeTiming

  • {PerformanceNodeTiming}

This property is an extension by Node.js. It is not available in Web browsers.

An instance of the PerformanceNodeTiming class that provides performance metrics for specific Node.js operational milestones.

Real world usage

The performance.nodeTiming property can be used to get performance metrics for specific Node.js operational milestones. This can be useful for debugging performance issues or for optimizing your code.

For example, you can use the performance.nodeTiming.bootstrapComplete property to get the time it took for Node.js to load and initialize. You can use this information to identify and fix any performance bottlenecks in your Node.js application.

The following code snippet shows how to use the performance.nodeTiming property:

const { performance } = require("perf_hooks");

// Get the performance metrics for specific Node.js operational milestones
const nodeTiming = performance.nodeTiming;

// Output the performance metrics
console.log(nodeTiming);

What is performance.now()?

performance.now() is a function that returns the current time in milliseconds, with high precision. This means that it can measure time intervals down to the microsecond level.

How does performance.now() work?

performance.now() uses the high-resolution timer of the operating system to measure the current time. This timer is typically more accurate than the system clock, which is used by most other timing functions.

Why use performance.now()?

You should use performance.now() when you need to measure time intervals with high precision. This is useful for tasks such as:

  • Measuring the performance of your code

  • Creating animations

  • Synchronizing events

Example:

The following code measures the time it takes to execute a function:

const startTime = performance.now();

// Execute the function
const result = myFunction();

const endTime = performance.now();

console.log(`Function took ${endTime - startTime} milliseconds to execute`);

Potential applications:

performance.now() can be used in a variety of applications, such as:

  • Performance testing

  • Game development

  • Audio and video editing

  • Scientific research


Performance Resource Timing Buffer Size

  • What is it?

It's like a storage space in your computer that holds information about how long it takes for web pages and resources to load. Specifically, it tracks events related to loading resources like images, scripts, and stylesheets.

  • Why is it important?

It helps you understand the performance of your website and identify any bottlenecks or slowdowns.

  • How to set the buffer size?

You can set the buffer size using the setResourceTimingBufferSize function. For example:

performance.setResourceTimingBufferSize(500); // Set the buffer size to 500 entries
  • Real-world applications:

  • Website performance optimization: Identify performance issues and optimize loading times.

  • Debugging: Track specific resource loading events to isolate problems.

  • Third-party resource monitoring: Monitor the behavior of external resources (e.g., ads) on your website.


performance.timeOrigin

  • What is it?

    • The timeOrigin property of the performance object specifies the high-resolution millisecond timestamp at which the current Node.js process began, measured in Unix time.

  • Simplified Explanation:

    • Imagine you have a stopwatch that starts ticking as soon as your Node.js program starts running. The timeOrigin property tells you the exact millisecond when that stopwatch started.

  • Code Snippet:

    const timeOrigin = performance.timeOrigin;
    console.log(
      `The Node.js process started at ${timeOrigin} milliseconds since the epoch.`
    );
  • Real-World Application:

    • You can use timeOrigin to measure the elapsed time of your program or to synchronize timestamps across multiple processes.

Example: Measuring Program Execution Time

const start = performance.now();

// Do some stuff...

const end = performance.now();

console.log(`The program took ${end - start} milliseconds to execute.`);

This code will output the time it took for the program to run between the start and end timestamps.

Example: Synchronizing Timestamps

const timeOrigin = performance.timeOrigin;

// Process 1
const timestamp1 = performance.now() + timeOrigin;

// Process 2
const timestamp2 = performance.now() + timeOrigin;

console.log(`Timestamp 1: ${timestamp1}`);
console.log(`Timestamp 2: ${timestamp2}`);

This code will output the timestamps from two different processes, synchronized to the same starting point using timeOrigin.


The performance.timerify() method in Node.js allows you to measure the running time of a function and see how long it takes to execute. It is especially useful for debugging and optimizing code performance.

To use performance.timerify(), you first need to create a PerformanceObserver object and subscribe it to the 'function' event type. This will allow you to access the timing details of the wrapped function.

Here's how you can use performance.timerify() to measure the running time of a function:

const { performance, PerformanceObserver } = require("node:perf_hooks");

function someFunction() {
  console.log("hello world");
}

const obs = new PerformanceObserver((list) => {
  console.log(list.getEntries()[0].duration);
});
obs.observe({ entryTypes: ["function"] });

// A performance timeline entry will be created
performance.timerify(someFunction)();

In this example, the someFunction function is wrapped with performance.timerify() and then executed. The PerformanceObserver object is subscribed to the 'function' event type and will log the duration of the function call to the console.

You can also use performance.timerify() to measure the running time of a function that returns a promise:

const { performance, PerformanceObserver } = require("node:perf_hooks");

function someAsyncFunction() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("hello world");
    }, 100);
  });
}

const obs = new PerformanceObserver((list) => {
  console.log(list.getEntries()[0].duration);
});
obs.observe({ entryTypes: ["function"] });

// A performance timeline entry will be created
performance
  .timerify(someAsyncFunction)()
  .then(() => {
    obs.disconnect();
  });

In this example, the someAsyncFunction function returns a promise that resolves after 100 milliseconds. The performance.timerify() method is used to wrap the function and the PerformanceObserver object is used to log the duration of the function call to the console.

performance.timerify() is a powerful tool that can help you understand the performance of your code. It can be used to identify bottlenecks and optimize your code for better performance.

Here are some potential applications of performance.timerify() in the real world:

  • Debugging performance issues in production code

  • Optimizing code for better performance

  • Profiling code to identify potential bottlenecks

  • Measuring the performance of different algorithms or data structures


performance.toJSON()

What is it?

performance.toJSON() converts the performance object into a JSON object. This allows you to easily store or transfer the performance data for analysis or visualization.

How to use it:

const performanceData = performance.toJSON();

Real-world example:

You can use performance.toJSON() to log performance data to the console for debugging purposes.

console.log(performance.toJSON());

Potential applications:

  • Performance monitoring and analysis

  • Benchmarking and performance comparisons

  • Debugging and troubleshooting performance issues

  • Identifying performance bottlenecks


Event: 'resourcetimingbufferfull'

Explanation:

When your browser is keeping track of how long it takes for certain actions to happen, like loading a webpage or a video, it keeps this information in a special storage area called the "resource timing buffer."

Sometimes, this storage area can get full if there are too many actions happening at once. When this happens, the browser triggers an event called 'resourcetimingbufferfull'.

How to respond:

When this event happens, you can tell the browser to either clear out the old information in the storage area or make the storage area bigger.

Real-world example:

Imagine you're visiting a website with a lot of videos. If you click on multiple videos at the same time, the browser might have trouble keeping track of how long each video takes to load. Clearing out the old information in the storage area or making it bigger would help the browser keep up.

Code example:

performance.addEventListener("resourcetimingbufferfull", () => {
  // Clear the old information in the storage area
  performance.clearResourceTimings();

  // Or make the storage area bigger
  performance.setResourceTimingBufferSize(largerSize);
});

Potential applications:

  • Measuring the performance of webpages and web applications

  • Troubleshooting performance issues

  • Optimizing the loading of resources (e.g., images, videos)


Class: PerformanceEntry

PerformanceEntry is a class that represents a single performance entry. A performance entry can be created using the performance.mark(), performance.measure(), or performance.getEntries() methods. Each entry has a name, a start time, a duration, and a timestamp. The name is a string that identifies the entry. The start time is a number that represents the time at which the entry was created. The duration is a number that represents the time that elapsed between the start time and the end time of the entry. The timestamp is a number that represents the time at which the entry was created.

Properties

  • name: The name of the entry.

  • startTime: The start time of the entry.

  • duration: The duration of the entry.

  • timestamp: The timestamp of the entry.

Methods

  • toJSON(): Returns a JSON representation of the entry.

Real-world examples

  • Measuring the performance of a function:

const startTime = performance.now();
const result = myFunction();
const endTime = performance.now();
const duration = endTime - startTime;
console.log(`The function took ${duration} milliseconds to execute.`);
  • Measuring the performance of a web page:

const startTime = performance.now();
window.addEventListener("load", () => {
  const endTime = performance.now();
  const duration = endTime - startTime;
  console.log(`The page took ${duration} milliseconds to load.`);
});

Potential applications

  • Performance optimization: PerformanceEntry can be used to identify performance bottlenecks in code.

  • Debugging: PerformanceEntry can be used to debug performance issues.

  • Monitoring: PerformanceEntry can be used to monitor performance over time.


What is performanceEntry.duration?

performanceEntry.duration is a property that represents the total amount of time, in milliseconds, that it took for a specific performance entry to complete.

Real World Applications

This property can be used to measure the performance of various aspects of your web application, such as:

  • The time it takes for a web page to load

  • The time it takes for a user to interact with a specific element on the page

  • The time it takes for a network request to complete

Potential Applications

This property can be used to:

  • Identify bottlenecks in your web application

  • Improve the user experience by optimizing the performance of your application

  • Track the performance of your application over time

Example

The following code snippet shows how to use the performanceEntry.duration property:

const entry = performance.getEntriesByType("navigation")[0];

console.log(`The page load took ${entry.duration} milliseconds`);

This code will output something like the following:

The page load took 1234 milliseconds

This output shows that it took 1234 milliseconds for the page to load. This information can be used to identify bottlenecks in the page load process and improve the performance of the application.


performanceEntry.entryType

  • Simplified Explanation:

The performanceEntry.entryType property tells you what kind of performance measurement the entry represents. It can be one of several types, including:

  • Node.js Only:

    • 'node': A general performance entry for Node.js.

    • 'gc': A garbage collection entry.

    • 'function': A function execution entry.

    • 'http2': An HTTP/2 request or response entry.

    • 'http': An HTTP request or response entry.

  • Web Only:

    • 'mark': A manual timestamp added to the timeline.

    • 'measure': A measurement of time or resources between two marks.

  • Detailed Explanation:

The performanceEntry.entryType property provides more information about the specific type of performance measurement the entry represents. This can be helpful in understanding and interpreting the data in the entry.

  • Real-World Complete Code Implementation and Example:

const { performance } = require("perf_hooks");

// Start a mark
performance.mark("start");

// Do some work
setTimeout(() => {
  // End a mark
  performance.mark("end");

  // Get the measure between the two marks
  const measure = performance.measure("my-measure", "start", "end");

  // Log the measure
  console.log(measure);
}, 1000);

In this example, we use the performance.mark() function to create two marks, 'start' and 'end', and then we use the performance.measure() function to create a measure, 'my-measure', between the two marks. The measure provides information about the time taken between the two marks, which can be useful for performance analysis.

  • Potential Applications in Real World:

The performanceEntry.entryType property can be used for a variety of performance analysis and optimization tasks, including:

  • Identifying performance bottlenecks

  • Optimizing code execution

  • Understanding the impact of specific operations on performance

  • Comparing the performance of different implementations

  • Tracking the performance of a long-running process


performanceEntry.name

  • Simplified Explanation: This is the name of the performance entry. It tells you what kind of event this is, such as "page load" or "function execution".

  • Example:

const performanceEntry = performance.getEntriesByName("page load")[0];
console.log(performanceEntry.name); // "page load"

Real-World Applications

  • Performance Monitoring: You can use this property to identify and track specific events in your application's performance.

  • Debugging: You can use it to identify the cause of performance issues by comparing the names of performance entries before and after making code changes.


What is performanceEntry.startTime?

performanceEntry.startTime is a property of a Performance Entry object, which provides information about a specific performance metric in the browser. In this case, performanceEntry.startTime represents the starting time of the Performance Entry.

Simplified Explanation:

Imagine you're running a race and you have a stopwatch to measure your performance. The performanceEntry.startTime is like the moment you start the stopwatch, marking the beginning of your race.

Real-World Complete Code Implementation:

// Get the PerformanceEntry for a specific metric, such as page load
const performanceEntry = performance.getEntriesByName("pageLoad")[0];

// Retrieve the starting time of the PerformanceEntry
const startTime = performanceEntry.startTime;

console.log(`Page load started at: ${startTime} milliseconds`);

Potential Applications:

  • Performance Monitoring: Track the starting time of specific events, such as page load or API calls, to identify potential bottlenecks or areas for optimization.

  • User Experience Analysis: Determine the time it takes for certain elements on a web page to appear or become interactive, providing insights into the user's experience.

  • Benchmarking: Compare the starting times of performance entries across different browsers or devices to evaluate performance differences.


Class: PerformanceMark

Definition: PerformanceMark is a class that represents a mark in the performance timeline. A mark is a user-defined timestamp that can be used to identify a specific event in the performance of a web page.

Extends: PerformanceMark extends the PerformanceEntry class, which provides common properties and methods for all performance entries.

Properties:

  • name: The name of the mark.

  • entryType: The type of entry, which is always "mark".

  • startTime: The timestamp of the mark, in milliseconds relative to the start of the performance timeline.

  • detail: Additional details about the mark, such as a description or a stack trace.

Methods:

  • toJSON(): Returns a JSON representation of the mark.

Example:

const markName = 'MyMark';
performance.mark(markName);

In this example, the performance.mark() method is used to create a mark named "MyMark". The mark is recorded in the performance timeline at the current time.

Potential Applications:

  • Measuring performance of specific events: Marks can be used to measure the performance of specific events, such as loading a page, executing a function, or rendering a component.

  • Identifying performance bottlenecks: By comparing marks from different parts of the application, developers can identify areas where performance is suffering and target them for optimization.

  • Creating custom performance reports: Marks can be used to create custom performance reports that provide detailed information about the performance of a web page.


performanceMark.detail

Simplified Explanation

When you create a performance mark using the mark() method, you can provide additional information about the mark in the detail property. This information can be anything you want, but it's typically used to provide a more descriptive name or context for the mark.

Example

performance.mark("myMark", {
  detail: "This is my mark",
});

In this example, the detail property is set to the string "This is my mark". This additional information can be useful when you're trying to find or identify a specific mark later on.

Real-World Application

Performance marks can be used to track the performance of your application in a variety of ways. For example, you could use marks to track the time it takes to load a page, or the time it takes to execute a specific function. By adding detail to your marks, you can make it easier to identify and track down performance problems in your application.


Simplified Explanation of PerformanceMeasure Class

What is PerformanceMeasure?

Imagine you're running a race (a program). You can use PerformanceMeasure to track how long certain parts of the race took.

How to Use PerformanceMeasure

To use PerformanceMeasure, you first need to start a measure using the Performance.measure() method. This creates a PerformanceMeasure object.

Once you have a PerformanceMeasure object, you can access information about the measure, such as:

  • name: The name you gave the measure when you created it.

  • startTime: The time when you started the measure.

  • endTime: The time when you stopped the measure.

  • duration: The time it took to complete the measure.

Real-World Example

Let's say you want to measure how long it takes to load a web page. You could use PerformanceMeasure to do this by following these steps:

  1. Start a measure when the page starts loading.

  2. Stop the measure when the page is fully loaded.

  3. Access the duration property of the PerformanceMeasure object to get the time it took to load the page.

Potential Applications

PerformanceMeasure can be used to measure the performance of any part of a program. Here are some potential applications:

  • Measuring the time it takes to load a website or web application.

  • Measuring the time it takes to execute a function or block of code.

  • Identifying performance bottlenecks in a program.

  • Comparing the performance of different versions of a program.

Code Implementation

To start a PerformanceMeasure, you can use the following syntax:

const measure = performance.measure("my-measure");

To stop the PerformanceMeasure, you can use the following syntax:

measure.stop();

To access the properties of the PerformanceMeasure, you can use the following syntax:

console.log(measure.name); // "my-measure"
console.log(measure.startTime); // The time when the measure was started
console.log(measure.endTime); // The time when the measure was stopped
console.log(measure.duration); // The time it took to complete the measure

performanceMeasure.detail

Each PerformanceMeasure has a detail property, which provides additional information about the measurement. The detail property can be any value, but it is typically a string or an object.

Example:

const measure1 = performance.measure("my-measure");

console.log(measure1.detail); // 'Some additional information'

Here, the detail property of measure1 is a string containing some additional information about the measurement.

Applications:

The detail property can be useful for debugging purposes, or for providing additional information to other tools that consume performance data. For example, the detail property could be used to store the name of the function that was being measured, or the number of times the function was called.


Class: PerformanceNodeEntry

The PerformanceNodeEntry class in the perf_hooks module represents a detailed Node.js timing entry. It is used to gather performance data about specific Node.js operations, such as the execution time of a function or the time spent in a particular module.

Properties:

  • name: The name of the timing entry.

  • entryType: The type of timing entry. For PerformanceNodeEntry, this is always "node".

  • startTime: The start time of the timing entry, in milliseconds since the Node.js process started.

  • duration: The duration of the timing entry, in milliseconds.

  • nodeTiming: An object containing detailed Node.js timing information, including:

    • execution: The execution time of JavaScript code, in milliseconds.

    • idle: The idle time, in milliseconds.

    • gc: The garbage collection time, in milliseconds.

    • prepare: The prepare time, in milliseconds.

    • compile: The compile time, in milliseconds.

Methods:

  • toJSON(): Returns a JSON representation of the timing entry.

Usage:

To use the PerformanceNodeEntry class, you can use the performance.timerify() function to create a new timing entry. For example:

const { performance } = require("perf_hooks");

const timer = performance.timerify(function () {
  // Do something
});

timer.start();

// Do something

timer.stop();

console.log(timer.duration); // Output: 100 (milliseconds)

Applications:

The PerformanceNodeEntry class can be used to:

  • Measure the performance of specific Node.js operations.

  • Identify performance bottlenecks in your code.

  • Optimize your code for better performance.


What is performanceNodeEntry.detail?

performanceNodeEntry.detail is a property of the performanceNodeEntry object in the perf_hooks module. It provides additional details about the entry, specific to the type of entry.

How to use performanceNodeEntry.detail

The performanceNodeEntry.detail property is an any type, meaning it can contain any type of data. The specific type of data contained in this property will depend on the type of entry.

For example, if the entry is a gc entry, the detail property will contain an object with information about the garbage collection event. This object will include properties such as:

  • collections: The number of garbage collection events that occurred during the interval.

  • heapIncremental: The amount of memory that was allocated in the incremental heap during the interval.

  • heapSnapshot: A snapshot of the heap at the end of the interval.

If the entry is a http entry, the detail property will contain an object with information about the HTTP request or response. This object will include properties such as:

  • method: The HTTP method used for the request or response.

  • status: The HTTP status code for the request or response.

  • url: The URL of the request or response.

Real-world applications

The performanceNodeEntry.detail property can be used to get more information about the performance of your application. This information can be used to identify bottlenecks and improve performance.

For example, you can use the detail property of a gc entry to see how often garbage collection is occurring and how much memory is being allocated. This information can help you identify if your application is generating too much garbage and causing performance problems.

You can also use the detail property of a http entry to see how long it takes for your application to process HTTP requests and responses. This information can help you identify if your application is spending too much time waiting for network requests or responses.

Code example

The following code example shows how to use the performanceNodeEntry.detail property:

const { PerformanceObserver } = require('perf_hooks');

const obs = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log(`Entry type: ${entry.entryType}`);
    console.log(`Entry detail:`);
    console.dir(entry.detail, { depth: null });
  }
});

obs.observe({ entryTypes: ['gc', 'http'] });

This code will create a new PerformanceObserver and observe two types of performance entries: gc and http. When a new entry is recorded, the PerformanceObserver will be called and the detail property of the entry will be logged to the console.


performanceNodeEntry.flags

The performanceNodeEntry.flags property provides additional information about garbage collection operations when performanceEntry.entryType is equal to 'gc'. The value can be one of the following flags:

Flags:

  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_NO: No flags are set.

  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED: The garbage collection operation was triggered by a call to gc() with the constructRetained option set to true.

  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_FORCED: The garbage collection operation was forced, meaning it was not triggered by the normal garbage collection algorithm.

  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING: The garbage collection operation processed phantom objects synchronously.

  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE: The garbage collection operation collected all available garbage.

  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY: The garbage collection operation collected all external memory.

  • perf_hooks.constants.NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE: The garbage collection operation was scheduled to run during an idle period.

Real-World Application:

The performanceNodeEntry.flags property can be used to gain insight into the garbage collection behavior of your application. For example, you can use it to determine if garbage collection is being triggered too frequently or if it is not collecting all of the available garbage. This information can help you optimize your application's performance.

Example:

const perf_hooks = require('perf_hooks');

perf_hooks.on('gc', (info) => {
  console.log(`GC flags: ${info.flags}`);
});

This example will log the performanceNodeEntry.flags property for every garbage collection operation.

Conclusion:

The performanceNodeEntry.flags property provides a valuable way to monitor and analyze garbage collection operations in your application. This information can help you optimize your application's performance and ensure that it is running efficiently.


Simplified Explanation

When you're running a Node.js application, the JavaScript engine performs regular "garbage collection" to free up memory that's no longer being used. The performanceNodeEntry.kind property tells you the specific type of garbage collection that occurred:

Types of Garbage Collection

  • Major: This is a thorough cleanup, scanning through all memory to identify and remove unused objects. It takes the most time and releases the most memory.

  • Minor: Similar to major, but it scans a smaller portion of memory and typically takes less time.

  • Incremental: A continuous cleanup process that happens while the application is running. It's less intensive and releases less memory compared to the other types.

  • WeakCB: This type runs when the application is idle and removes references to objects that are no longer used.

Real-World Implementations

Here's how you can use the performanceNodeEntry.kind property in a Node.js application:

// node_performance_example.js

const { performance } = require("perf_hooks");

performance.mark("start");

// Some code that allocates a lot of memory

performance.measure("measure", "start");

const entry = performance.getEntriesByName("measure")[0];
console.log(`Type of garbage collection: ${entry.detail}`);

In this example, we create a performance mark and measure to track the memory usage of a specific code block. We then retrieve the performance entry and check the detail property (which is now used instead of performanceNodeEntry.kind) to determine the type of garbage collection that occurred while the code block was executing.

Potential Applications

  • Memory optimization: Understanding the types of garbage collection that are happening can help you optimize your application's memory usage. For example, if you notice a lot of minor garbage collections, you may need to increase the heap size.

  • Performance monitoring: You can use the performanceNodeEntry.kind property to monitor the performance of your garbage collection system. For example, if you see a lot of major garbage collections, it may indicate a memory leak or performance issue.


Garbage Collection (GC) in Node.js

When a Node.js program is running, it uses memory to store data and objects. Over time, as the program runs, it may no longer need some of the objects it created. These objects become "garbage" that needs to be cleaned up to free up memory.

GC is the automatic process in Node.js that finds and removes these unneeded objects, freeing up memory for the program to use.

Types of GC

Node.js has four types of GC:

  1. Major GC: Performs a deep scan of the entire memory heap, freeing up all unneeded objects. This type of GC is the most time-consuming.

  2. Minor GC: Performs a quick scan of the memory heap, freeing up recently allocated objects. This type of GC is less time-consuming than Major GC.

  3. Incremental GC: Scans the memory heap incrementally, freeing up unneeded objects as it goes. This type of GC is ongoing and has minimal impact on program performance.

  4. Weak CB GC: Scans the memory heap for objects that have weak references (e.g., objects that are not directly accessible by the program). This type of GC is less common than the other three.

GC Flags

When GC is performed, it can have different flags set, which affect its behavior:

  1. NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED: Indicates that the GC was triggered by constructing a retained value.

  2. NODE_PERFORMANCE_GC_FLAGS_FORCED: Indicates that the GC was forced manually by the program or by a memory leak.

  3. NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING: Indicates that the GC is processing phantom references (objects that are not accessible by the program but are still held by other objects).

  4. NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE: Indicates that the GC is collecting all garbage, regardless of its age.

  5. NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY: Indicates that the GC is collecting garbage from external memory (e.g., memory used by a child process).

  6. NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE: Indicates that the GC has been scheduled to run when the system is idle.

Performance Entry Object

When GC is performed, a performance entry object is created with the following properties:

  • type: "gc" to indicate that the entry is related to GC.

  • detail: An object with the following properties:

    • kind: The type of GC performed (Major, Minor, Incremental, or Weak CB).

    • flags: The flags that were set during the GC.

Real-World Examples

GC is constantly running in the background in Node.js. You can observe its behavior using the performance.getEntries() function:

const entries = performance.getEntries().filter((entry) => entry.type === "gc");
for (const entry of entries) {
  console.log(entry.detail.kind, entry.detail.flags);
}

This code will print the type of GC performed and the flags that were set.

Potential Applications

GC is essential for keeping Node.js programs running efficiently. It helps prevent memory leaks and ensures that the program has enough memory to operate smoothly.


HTTP Details in Performance Entries

What is an HTTP Performance Entry?

When you visit a website, your browser tracks how long it takes to load different parts of the page, such as images and scripts. This information is stored in performance entries.

HTTP Performance Entry Details

If a performance entry is of type "http", it will have additional details in the performanceNodeEntry.detail property. These details depend on the name of the performance entry.

HttpClient Entries

If the performance entry's name is "HttpClient", the details will include:

  • req: Information about the request sent to the server, including method (e.g., "GET" or "POST"), URL, and headers.

  • res: Information about the response received from the server, including status code (e.g., 200 for "OK"), status message, and headers.

HttpRequest Entries

If the performance entry's name is "HttpRequest", the details will also include:

  • req: Request information (same as HttpClient).

  • res: Response information (same as HttpClient).

Usage

These details can be used for diagnostic purposes, such as:

  • Identifying slow HTTP requests

  • Debugging server issues

  • Improving website performance

Real-World Example

To use these details, you can use the PerformanceObserver API. Here's an example:

const observer = new PerformanceObserver((entries) => {
  entries.forEach((entry) => {
    if (entry.type === "http") {
      const details = entry.detail;
      console.log(`Request: ${details.req.url}`);
      console.log(
        `Status: ${details.res.statusCode} ${details.res.statusMessage}`
      );
    }
  });
});

observer.observe({ entryTypes: ["http"] });

This script will log information about HTTP requests and responses to the console. It can be used to identify performance bottlenecks or issues.


HTTP/2 Performance Monitoring

When you're monitoring the performance of HTTP/2 connections, the performanceEntry.detail property provides additional information about the connection.

Http2Stream

If you're tracking an Http2Stream, the detail property contains:

  • bytesRead: Number of bytes received on this stream

  • bytesWritten: Number of bytes sent on this stream

  • id: Identifier of the stream

  • timeToFirstByte: Time in milliseconds from the start of the connection to when the first byte was received

  • timeToFirstByteSent: Time in milliseconds from the start of the connection to when the first byte was sent

  • timeToFirstHeader: Time in milliseconds from the start of the connection to when the first header was received

Http2Session

If you're tracking an Http2Session, the detail property contains:

  • bytesRead: Total number of bytes received on the session

  • bytesWritten: Total number of bytes sent on the session

  • framesReceived: Number of HTTP/2 frames received

  • framesSent: Number of HTTP/2 frames sent

  • maxConcurrentStreams: Maximum number of streams open at any time

  • pingRTT: Time in milliseconds between sending a PING frame and receiving a response (if any)

  • streamAverageDuration: Average duration of all streams in milliseconds

  • streamCount: Number of streams processed

  • type: Either 'server' or 'client' to identify the server or client session

Real-World Applications

Here's a simple example of how you might use this information to analyze HTTP/2 performance:

const { performance } = require("perf_hooks");

// Create an observer to track HTTP/2 performance
const observer = new performance.PerformanceObserver((list) => {
  list.getEntries().forEach((entry) => {
    if (entry.type === "http2") {
      console.log(`HTTP/2 session: ${entry.name}`);
      const detail = entry.detail;

      // Print out some performance metrics
      console.log(`  Bytes read: ${detail.bytesRead}`);
      console.log(`  Bytes written: ${detail.bytesWritten}`);
      console.log(`  Frames received: ${detail.framesReceived}`);
      console.log(`  Frames sent: ${detail.framesSent}`);
      console.log(`  Max concurrent streams: ${detail.maxConcurrentStreams}`);
    }
  });
});

// Start observing HTTP/2 performance
observer.observe({ entryTypes: ["http2"] });

By monitoring these metrics, you can identify potential performance bottlenecks and optimize your HTTP/2 connections.


Timerify ('function')

This is a special type of performance entry that is created when the performance.timerify() function is called. The detail property of the performance entry will be an array of the input arguments passed to the timed function.

For example:

const perf = require("perf_hooks");

function myFunction(a, b) {
  // Do something
}

perf.timerify(myFunction);

myFunction(1, 2);

const entry = perf.getEntriesByName("myFunction")[0];

console.log(entry.detail); // [1, 2]

Timerify can be used to measure the performance of any function. It is particularly useful for measuring the performance of asynchronous functions, such as those that make network requests or perform I/O operations.

Real-world applications:

  • Identifying performance bottlenecks in code

  • Optimizing the performance of critical functions

  • Debugging performance issues


Simplified Explanation of Net Performance Entry Details

When you measure the performance of your web application, you can collect information about network requests using the net performance entry type. This entry provides details about the network connection and the specific request that was made.

Detail Properties for Connect Request

If the name property of the net performance entry is equal to connect, then the detail property will contain additional information about the connection. This information includes:

  • host: The hostname or IP address of the server that the connection was made to.

  • port: The port number that was used for the connection.

Real-World Code Implementation

The following code snippet shows how to access the detail property of a net performance entry:

const { performance } = require("perf_hooks");

const entry = performance
  .getEntriesByType("net")
  .find((entry) => entry.name === "connect");

if (entry) {
  const { host, port } = entry.detail;
  console.log(`Connection to ${host}:${port} was established.`);
}

Potential Applications

The net performance entry and its detail property can be used for various applications, such as:

  • Network Troubleshooting: You can analyze the host and port properties to identify any connectivity issues or performance bottlenecks.

  • Performance Optimization: By monitoring the duration of connect requests, you can identify areas for performance improvements, such as optimizing DNS lookups or using faster servers.

  • Security Monitoring: You can use the host property to detect suspicious network connections or identify potential attacks.


DNS (Domain Name System)

The DNS is an internet service that translates human-readable website names like "www.example.com" into computer-readable IP addresses like "192.0.2.1". When you visit a website, your computer first needs to look up the IP address of the website's domain name using the DNS.

Performance API

The Performance API in Node.js allows you to measure the performance of your code. When using the Performance API to measure DNS performance, the type of the performance entry will be 'dns'.

Performance Entry Detail

The detail property of the performance entry contains additional information about the DNS lookup. The content of the detail property depends on the name of the performance entry:

  • If name is 'lookup', the detail property will contain the following:

    • hostname: The hostname being looked up.

    • family: The requested IP address family (e.g., 'IPv4', 'IPv6').

    • hints: Whether or not to use hints to speed up the lookup.

    • verbatim: Whether or not to return the verbatim response.

    • addresses: An array of IP addresses returned by the lookup.

  • If name is 'lookupService', the detail property will contain the following:

    • host: The hostname being looked up.

    • port: The port number being looked up.

    • hostname: The hostname for the service.

    • service: The service being looked up.

  • If name is 'queryxxx' or 'getHostByAddr', the detail property will contain the following:

    • host: The hostname being queried.

    • ttl: The time-to-live (TTL) of the DNS record.

    • result: The result of the query.

Real World Example

The following code shows how to use the Performance API to measure the performance of a DNS lookup:

const { performance } = require("perf_hooks");

const startTime = performance.now();
const host = "www.example.com";
const entry = performance.mark("dnsLookup");
const addresses = await dns.lookup(host);
performance.measure("dnsLookup", startTime, entry.name);
console.log(
  `DNS lookup for ${host} took ${
    performance.getEntriesByName("dnsLookup")[0].duration
  } milliseconds.`
);

Potential Applications

The Performance API can be used to identify performance bottlenecks in your code. For example, if DNS lookups are taking a long time, you can optimize your code to use a faster DNS server or to cache DNS results.


PerformanceNodeTiming Class

Overview

The PerformanceNodeTiming class in Node.js provides timing information about the Node.js runtime itself. It is not accessible to users directly; instead, instances of this class are returned by the performance.getEntries() method when entryType is set to "node".

Properties

The PerformanceNodeTiming class has the following properties:

  • entryType: Always set to "node".

  • name: A string describing the timing event.

  • startTime: The start time of the event, in milliseconds since the Node.js process started.

  • duration: The duration of the event, in milliseconds.

Usage

Here is an example of using the PerformanceNodeTiming class:

// Get all performance entries
const entries = performance.getEntriesByType("node");

// Iterate over the entries and log their names and durations
for (const entry of entries) {
  console.log(`${entry.name}: ${entry.duration}ms`);
}

Potential Applications

  • Monitoring the performance of Node.js applications

  • Identifying bottlenecks in Node.js code

  • Optimizing Node.js applications for performance


performanceNodeTiming.bootstrapComplete

  • {number}

This property represents the high-resolution millisecond timestamp at which the Node.js process completed bootstrapping. If bootstrapping has not yet finished, the property has the value of -1.

In simple terms:

The bootstrapComplete property tells you when the Node.js process finished loading all the necessary modules and libraries it needs to run your code.

Code snippet:

const perfHooks = require("perf_hooks");

// Get the bootstrap complete timestamp
const bootstrapCompleteTimestamp =
  perfHooks.performance.nodeTiming.bootstrapComplete;

// Check if bootstrapping has finished (timestamp is not -1)
if (bootstrapCompleteTimestamp !== -1) {
  console.log(`Bootstrapping finished at ${bootstrapCompleteTimestamp} ms`);
} else {
  console.log("Bootstrapping has not yet finished");
}

Real-world application:

  • Monitoring the performance of Node.js applications

  • Identifying bottlenecks in the bootstrapping process

  • Optimizing the loading of modules and libraries


Performance Node Timing.environment

Simplified Explanation:

The performanceNodeTiming.environment property in Node.js tells you the exact moment when the Node.js environment was ready to start running your code. It's a very precise timestamp, measured in milliseconds since the computer's clock started.

Detailed Explanation:

When you run a Node.js program, the Node.js environment needs to do some setup work before it can execute your code. This includes loading all the necessary modules and libraries, creating the objects that your code will use, and setting up any event listeners.

The performanceNodeTiming.environment property tells you when this setup work was completed. It's useful for understanding how long it takes for the Node.js environment to get ready to run your code.

Code Snippet:

const { performance } = require("perf_hooks");

// Get the timestamp when the Node.js environment was initialized
const environmentTimestamp = performance.nodeTiming.environment;

console.log(`Node.js environment initialized at: ${environmentTimestamp} ms`);

Potential Applications:

  • Measuring the startup time of Node.js applications

  • Identifying bottlenecks in Node.js environment setup

  • Optimizing the loading of modules and libraries

  • Debugging issues related to Node.js environment initialization


performanceNodeTiming.idleTime

Simplified Explanation:

Imagine a race car waiting at a stoplight. The idleTime measures how long the engine has been idling (not moving) while the light is red.

Detailed Explanation:

  • What it measures: The amount of time the JavaScript engine's event loop has been "waiting" (not running any tasks) within its event provider.

  • Not affected by CPU usage: Unlike other performance metrics like process.cpuUsage(), idleTime does not consider CPU usage. It only tracks the time the event loop is idle.

  • Unit: Milliseconds

Code Snippet:

const { performance } = require("perf_hooks");

const start = performance.now();
// Run some tasks...
const end = performance.now();

// Calculate the idle time during the tasks
const idleTime = performance.nodeTiming.idleTime / 1000; // Convert to seconds

console.log(`Tasks took ${end - start}ms to complete.`);
console.log(`Idle time during tasks: ${idleTime}s`);

Real-World Applications:

  • Performance optimization: Identifying bottlenecks in code execution by finding areas with excessive idle time.

  • Debugging event loop issues: Diagnosing why the event loop is not running tasks when expected.

  • Understanding application responsiveness: Evaluating how quickly the application responds to user input by analyzing idle time during user interactions.


Simplified Explanation:

Performance Node Timing

The performanceNodeTiming.loopExit property provides a snapshot of the current state of the Node.js event loop. It tells you when the event loop last exited, if it has already exited.

Event Loop Exit

The event loop is like a continuous cycle that runs in Node.js. It processes events, callbacks, and tasks that have been scheduled to run. When there are no more events to process, the event loop exits.

Usage:

You can use this property to track the time spent in the event loop. Knowing when the event loop exited can help you identify performance issues. For example, if you notice that the event loop is exiting frequently, it could mean that your code is doing too much work in the event loop and needs to be optimized.

Code Example:

const perfHooks = require("perf_hooks");

// Register a listener for the 'exit' event of the event loop
perfHooks.on("exit", () => {
  // Get the timestamp when the event loop exited
  const loopExitTime = perfHooks.performanceNodeTiming.loopExit;
  console.log(`Event loop exited at ${loopExitTime} ms`);
});

// Start a long-running task in the event loop
setTimeout(() => {
  // Do something that takes a long time
  for (let i = 0; i < 100000000; i++) {}
  // The event loop will exit when this task completes
}, 1000);

Real-World Applications:

  • Performance Profiling: Identifying bottlenecks and slowdowns in your code

  • Optimization: Fine-tuning your code to reduce event loop exits and improve performance

  • ** Debugging:** Helping you understand why your code is not behaving as expected


performanceNodeTiming.loopStart

Simplified Explanation:

The performanceNodeTiming.loopStart property tells you when the main loop of your Node.js application started running.

Detailed Explanation:

The event loop is the central mechanism that runs your Node.js application. It checks for events (like user input or timer triggers) and responds to them by executing code.

The loopStart property gives you the timestamp of when the event loop first started running. This is useful for measuring the overall performance of your application, as it tells you how long it took for the event loop to start processing events.

Real-World Complete Code Example:

// Get the performance timing information
const performance = require("perf_hooks").performance;

// Log the loop start time
console.log(performance.nodeTiming.loopStart);

Potential Applications:

  • Profiling application performance: You can use the loopStart property to measure the time it takes for your application to start up and respond to events. This can help you identify bottlenecks and improve performance.

  • Debugging event loop issues: If you're experiencing event loop delays, you can use the loopStart property to see if the event loop is starting slowly. This can help you troubleshoot and resolve event loop issues.


performanceNodeTiming.nodeStart

  • Concept: performanceNodeTiming.nodeStart is a high-resolution timestamp in milliseconds that represents when the Node.js process started. This timestamp is a valuable measurement for tracking the performance of your Node.js applications.

  • Simplified Explanation: Imagine your Node.js application is like a race car. performanceNodeTiming.nodeStart is like the starting line of the race, marking the exact moment when the car (your application) begins to execute.

  • Code Snippet:

const { performance } = require("perf_hooks");

// Get the nodeStart timestamp
const nodeStartTime = performance.nodeTiming.nodeStart;

// Calculate the amount of time since the application started (in milliseconds)
const timeSinceStart = performance.now() - nodeStartTime;

console.log(`Time since application start: ${timeSinceStart} milliseconds`);
  • Real-World Application: You can use performanceNodeTiming.nodeStart to:

    • Measure the overall performance of your application.

    • Identify bottlenecks and areas for performance improvement.

    • Track the performance of specific tasks or operations within your application.


Perf-hooks is a built-in node.js module that provides an easy and efficient way to measure the performance of a node.js application. It can be used to profile the performance of a single function, a series of functions, or even the entire application.

One of the most important things to know when profiling the performance of a node.js application is when the V8 platform was initialized. The V8 platform is the JavaScript engine that powers node.js, and its initialization can have a significant impact on the performance of your application.

The performanceNodeTiming.v8Start property contains the high resolution millisecond timestamp at which the V8 platform was initialized. This information can be used to determine how long it took for the V8 platform to initialize, and can be used to identify any potential performance bottlenecks.

Here is a simple example of how to use the performanceNodeTiming.v8Start property:

const perfHooks = require('perf_hooks');

const startTime = perfHooks.performance.nodeTiming.v8Start;

// Do some work

const endTime = perfHooks.performance.nodeTiming.v8Start;

console.log(`It took ${endTime - startTime} milliseconds to initialize the V8 platform`);

This example will output the amount of time it took for the V8 platform to initialize. This information can be used to identify any potential performance bottlenecks, and can help you to optimize the performance of your node.js application.


Class: PerformanceResourceTiming

Explanation: PerformanceResourceTiming is a JavaScript class that provides detailed network timing data about how long it takes for an application's resources to load. This information can be used to identify performance bottlenecks and improve the user experience.

Properties:

  • name: The name of the resource, such as "image.png" or "script.js".

  • startTime: The time when the resource request was started.

  • redirectStart: The time when the browser started to redirect the resource.

  • redirectEnd: The time when the browser finished redirecting the resource.

  • fetchStart: The time when the browser started to fetch the resource.

  • domainLookupStart: The time when the browser started to resolve the domain name of the resource.

  • domainLookupEnd: The time when the browser finished resolving the domain name of the resource.

  • connectStart: The time when the browser started to establish a connection to the server.

  • connectEnd: The time when the browser finished establishing a connection to the server.

  • secureConnectionStart: The time when the browser started to establish a secure connection to the server.

  • requestStart: The time when the browser started to send the request to the server.

  • responseStart: The time when the browser received the first byte of the response from the server.

  • responseEnd: The time when the browser received the last byte of the response from the server.

  • transferSize: The size of the resource in bytes.

  • encodedBodySize: The size of the request body in bytes, after encoding.

  • decodedBodySize: The size of the response body in bytes, after decoding.

Methods:

  • toJSON(): Returns a JSON representation of the object.

Example:

const performance = require("perf_hooks").performance;

const entry = performance.getEntriesByType("resource");
entry.forEach((resource) => {
  console.log(resource.name);
  console.log(resource.startTime);
  console.log(resource.redirectStart);
  console.log(resource.redirectEnd);
  console.log(resource.fetchStart);
  console.log(resource.domainLookupStart);
  console.log(resource.domainLookupEnd);
  console.log(resource.connectStart);
  console.log(resource.connectEnd);
  console.log(resource.secureConnectionStart);
  console.log(resource.requestStart);
  console.log(resource.responseStart);
  console.log(resource.responseEnd);
  console.log(resource.transferSize);
  console.log(resource.encodedBodySize);
  console.log(resource.decodedBodySize);
  console.log("-----------------------------");
});

Output:

image.png
1637630517636
undefined
undefined
1637630517637
1637630517637
1637630517637
1637630517641
1637630517642
undefined
1637630517643
1637630517671
1637630517672
10350
9639
5425
-----------------------------
script.js
1637630517676
undefined
undefined
1637630517677
1637630517677
1637630517677
1637630517679
1637630517680
undefined
1637630517681
1637630517709
1637630517710
18039
17560
5643
-----------------------------
index.css
1637630517714
undefined
undefined
1637630517716
1637630517716
1637630517716
1637630517717
1637630517718
undefined
1637630517719
1637630517738
1637630517739
23920
23330
6001
-----------------------------

Applications:

  • Identifying performance bottlenecks: By analyzing the timing data, developers can identify which resources are taking the longest to load and focus on optimizing those resources.

  • Improving user experience: By reducing the load time of resources, developers can improve the user experience and make their applications more responsive.

  • Monitoring application performance: By tracking the performance of resources over time, developers can monitor the health of their applications and identify any performance regressions.


performanceResourceTiming.workerStart

The performanceResourceTiming.workerStart property in perf_hooks returns the high resolution millisecond timestamp at immediately before dispatching the fetch request. If the resource is not intercepted by a worker the property will always return 0.

How to use:

const { performance } = require("perf_hooks");

const resourceTiming = performance.resourceTiming;

console.log(resourceTiming.workerStart);

performanceResourceTiming.redirectStart

This property in performanceResourceTiming interface represents the high-resolution millisecond timestamp that represents the start time of the fetch which initiates the redirect. If there is no redirect, this value is 0.

Real-world example:

The following code snippet creates a new PerformanceResourceTiming object with a redirectStart property set to 1234:

const performanceResourceTiming = {
  redirectStart: 1234,
};

Potential applications:

This property can be used to measure the time it takes for a browser to redirect to a new URL. This information can be used to improve the performance of a website by reducing the number of redirects.


performanceResourceTiming.redirectEnd

This is a number, specifically a high-resolution millisecond timestamp, that gets created immediately after receiving the final byte of the last redirect's response.

Simplified:

Every time a website redirects to another website, your browser will show a progress bar as it waits for the response from the new website. This time is measured and recorded in performanceResourceTiming.redirectEnd.

You can use this information to:

  • Find the total time it takes for a website to load.

  • Find the time taken for the redirects to complete.


Performance Resource Timing: fetchStart

Simplified Explanation:

Imagine you're making a request to a website or server. fetchStart is the exact moment when your computer or device starts fetching the requested resource. It's like the race starting once you've yelled, "Go!"

Detailed Explanation:

fetchStart is a high-precision timestamp (in milliseconds) that marks the instant when Node.js begins the process of retrieving a resource (such as a webpage, image, or script) from the network. This timestamp provides a reference point for measuring the duration of various stages in the resource retrieval process.

Example:

const perfHooks = require("perf_hooks");

perfHooks.once("fetchStart", (timestamp) => {
  console.log(`Fetch started at ${timestamp}`);
});

Real-World Applications:

  • Performance Monitoring: Measuring fetchStart allows developers to identify slowdowns or bottlenecks in the resource retrieval process.

  • Page Load Optimization: By knowing when resources start fetching, developers can optimize the order and timing of requests to improve website performance.

  • Resource Analysis: Understanding the timing of fetchStart can help developers pinpoint specific resources that are causing performance issues.


performanceResourceTiming.domainLookupStart – The Start Time of the Domain Lookup

  • Simplified explanation:

    When your browser starts loading a resource (like an image or a script) from a website, it first needs to look up the IP address of the website's server. This is called a "domain lookup." domainLookupStart tells you the exact time, in milliseconds, when this lookup started.

  • Code snippet:

const perfEntry = performance.getEntriesByName("script.js")[0];
console.log(perfEntry.domainLookupStart);
  • Real-world example:

    You can use this information to troubleshoot website performance issues. If the domainLookupStart time is very high, it could mean that your DNS server is slow or that the website you're trying to access is experiencing heavy traffic.

  • Potential applications:

    • Monitoring website performance

    • Diagnosing website performance issues

    • Optimizing website loading times


performanceResourceTiming.domainLookupEnd

  • {number}

Indicates the time, in milliseconds, when the domain name lookup for the resource ended. This is the time it took for the browser to look up the IP address for the domain name of the resource.

This metric can be useful for identifying performance bottlenecks in your application. If the domain lookup time is high, it could mean that there is a problem with your DNS server or that the domain name is not resolving correctly.

Real-world example:

const perfEntry = performance.getEntries()[0];

if (perfEntry.domainLookupEnd - perfEntry.domainLookupStart > 500) {
  console.log("Warning: Domain lookup took longer than 500ms");
}

In this example, we are checking if the domain lookup time took longer than 500 milliseconds. If it did, we log a warning message to the console. This could indicate that there is a problem with our DNS server or that the domain name is not resolving correctly.

Potential applications:

  • Identifying performance bottlenecks in your application

  • Diagnosing DNS issues

  • Monitoring the performance of your CDN


High-Resolution Timestamps with performance.resourceTiming.connectStart

Imagine you're playing a video game online. Your computer needs to connect to the game server to retrieve the game data. The connectStart property measures the time it takes for your computer to start establishing that connection.

Simplified Explanation:

connectStart tells us when your computer sends the first message to the server saying, "Hey, let's connect and get the game data."

Code Snippet:

console.log(performance.resourceTiming.connectStart); // Output: 123456789.123

Real-World Implementation:

  • Game Development: Developers can use connectStart to identify if the game server is taking too long to respond, which could cause players to experience lag.

  • Website Performance: Website owners can use connectStart to measure how quickly their website connects to external resources like images or videos. This helps improve website responsiveness.

Potential Applications:

  • Monitoring Server Performance: Track the speed at which servers respond to connection requests.

  • Identifying Network Issues: Detect network delays that may be affecting application performance.

  • Webpage Optimization: Improve website loading times by optimizing connection time to external resources.

  • Game Analytics: Collect data on player connection times to analyze server load and optimize gameplay.


performanceResourceTiming.connectEnd

  • Definition: It is a high-resolution timestamp in milliseconds that represents the moment when Node.js finishes establishing a connection to the server to fetch a resource.

In Plain English: Imagine you're sending a message to a friend. The connectEnd timestamp tells you the exact moment the connection to your friend's phone was established.

Code Example:

const { performance } = require("perf_hooks");

performance.mark("connect_start");
// Do something that takes time, like sending a request to a server
performance.mark("connect_end");

const timeTaken = performance.measure(
  "connect",
  "connect_start",
  "connect_end"
);
console.log(`Time taken to connect: ${timeTaken.duration} milliseconds`);

Real-World Application:

Analyzing the time taken to establish connections can help identify network performance issues. For example, if the connectEnd timestamp is significantly higher than expected, it could indicate slow network response times or issues with the server's ability to handle requests.


performanceResourceTiming.secureConnectionStart

This property is a millisecond timestamp that represents the exact moment when Node.js starts the process of making the current connection secure.

Simplified Explanation:

When you visit a website that uses HTTPS, your browser needs to make sure the connection is secure before it can send any data. This process involves exchanging encrypted information between your browser and the website's server. The secureConnectionStart property tells you the exact moment when Node.js starts this process.

Real-World Example:

Imagine you're visiting an online banking website. When you log in, your browser needs to establish a secure connection to the bank's server to protect your login information. The secureConnectionStart property can tell you exactly when the browser started this process, which can help diagnose any issues if the connection takes too long.

Potential Applications:

  • Detecting and troubleshooting network performance issues

  • Analyzing website security protocols

  • Optimizing connection times for web applications


performanceResourceTiming.requestStart

Simplified Explanation:

When you visit a website, your browser sends a request to the server to get the webpage. requestStart tells you the exact moment when your browser started receiving the response from the server. It's like the starting point of the race to get the webpage.

Technical Explanation:

performanceResourceTiming.requestStart is a property that measures the time in milliseconds since the browser started receiving the response from the server. It's part of the performanceResourceTiming object, which contains detailed information about the loading of a specific resource (like an image or a script).

Code Example:

const performance = require('perf_hooks');

// Start measuring the performance of a resource
const resourceTiming = performance.resourceTiming('image1');

// Check the time when the resource request started
console.log(`Request start: ${resourceTiming.requestStart} ms`);

Real-World Applications:

  • Performance Monitoring: To identify and fix performance bottlenecks in web applications.

  • Debugging: To pinpoint the exact cause of slow page loads.

  • Optimizing Load Times: By understanding how long it takes to receive data from the server, developers can make improvements to reduce loading times.


performanceResourceTiming.responseEnd

Explanation:

responseEnd is a high-precision timestamp that tells you when the last byte of a resource was received by Node.js or when the connection to the resource was closed, whichever happens first.

Simplified Explanation:

Imagine you're downloading a file from the internet. responseEnd is the exact moment when the entire file has been downloaded.

Code Snippet:

// Get the performance entry for a resource
const entry = performance.getEntriesByName("example.com")[0];

// Get the responseEnd timestamp
const responseEndTime = entry.responseEnd;

console.log(`The resource was downloaded in ${responseEndTime} milliseconds.`);

Real World Applications:

  • Performance Tuning: You can use responseEnd to identify slow resources that are affecting your application's performance.

  • Network Analysis: You can analyze the time it takes for resources to load and identify network bottlenecks or latency issues.

  • Debugging: You can use responseEnd to track down issues with resource loading and understand why a resource might be taking longer than expected to load.


performanceResourceTiming.transferSize

Explanation:

This property represents the total size of a fetched resource, including both the header information and the actual content (body) of the resource. It is measured in bytes.

Example:

const resourceTiming = performance.getEntriesByType('resource');

resourceTiming.forEach((timing) => {
  console.log(`Resource: ${timing.name}`);
  console.log(`Transfer size: ${timing.transferSize} bytes`);
});

Potential Applications:

  • Monitoring the performance of web requests, such as tracking the size of downloaded assets (e.g., images, CSS, JavaScript).

  • Identifying resources that are large and may be impacting page load time.

  • Comparing the performance of different web pages or resources to optimize performance.

  • Analyzing resource usage patterns to understand how users interact with a website.


performanceResourceTiming.encodedBodySize

  • number: A number representing the size (in octets) received from the fetch (HTTP or cache), of the payload body, before removing any applied content-codings.

Real World Example

You have a web page with multiple images. You want to know the size of the images in bytes before they are decoded by the browser.

Example

// Get the performance resource timing data for the current page
const performanceData = process.getPerformanceResourceTimingData();

// Get the encoded body size for the first resource
const encodedBodySize = performanceData[0].encodedBodySize;

console.log(`The encoded body size for the first resource is ${encodedBodySize} bytes`);

Output

The encoded body size for the first resource is 1024 bytes

What is performanceResourceTiming.decodedBodySize?

In web performance, it's important to know how long it takes to load and display a web page. This includes measuring the time it takes to download resources, such as images, videos, and CSS files.

performanceResourceTiming.decodedBodySize is a property that represents the size of the response body, after any content encoding (such as GZIP or Brotli) has been applied. This value is useful for understanding how much data was actually transferred over the network.

How to use performanceResourceTiming.decodedBodySize?

You can access the performanceResourceTiming.decodedBodySize property through the PerformanceResourceTiming API. This API is available in most modern browsers, including Chrome, Firefox, and Safari.

Here's an example of how to use the performanceResourceTiming.decodedBodySize property:

// Get the performance resource timing data
const entries = performance.getEntriesByType('resource');

// Find the entry for a specific resource
const entry = entries.find(entry => entry.name === 'my-image.jpg');

// Get the decoded body size
const decodedBodySize = entry.decodedBodySize;

// Log the decoded body size
console.log(`Decoded body size: ${decodedBodySize} bytes`);

Real-world applications

The performanceResourceTiming.decodedBodySize property can be used for a variety of purposes, including:

  • Performance optimization: By measuring the decoded body size of resources, you can identify which resources are taking the longest to load. This information can help you optimize your website's performance.

  • Security analysis: The decoded body size of a resource can be used to detect potential security vulnerabilities. For example, a large decoded body size could indicate that a resource has been inflated with unnecessary data.

  • Cost analysis: If you're using a pay-as-you-go cloud provider, you can use the decoded body size of resources to estimate your bandwidth costs.

Conclusion

The performanceResourceTiming.decodedBodySize property is a valuable tool for understanding and optimizing the performance of your website. By using this property, you can identify performance bottlenecks and make informed decisions about how to improve your website's load time.


performanceResourceTiming.toJSON()

Simplified Explanation:

The performanceResourceTiming.toJSON() method converts the PerformanceResourceTiming object into a JSON (JavaScript Object Notation) format. This allows you to easily share or store the performance data in a standard and readable format.

Real-World Implementation:

Let's say you want to log performance data for a website page. Here's how you could use performanceResourceTiming.toJSON() to log the data to the console:

// Create a new `PerformanceObserver` to observe resource performance
const observer = new PerformanceObserver((list) => {
  // Get the list of performance entries
  const entries = list.getEntries();

  // Convert the entries to JSON using `toJSON()`
  const entriesJSON = entries.map((entry) => entry.toJSON());

  // Log the JSON data to the console
  console.log(entriesJSON);
});

// Start the observer
observer.observe({ type: "resource" });

// Load some resources on the page (e.g., images, scripts)

Potential Applications:

  • Performance Monitoring: Track the performance of web pages, identify bottlenecks, and improve performance.

  • Debugging: Identify resource loading issues, such as slow-loading images or scripts.

  • Data Analysis: Analyze performance data over time to identify trends and patterns.

  • Performance Optimization: Use the data to optimize resource loading and improve page responsiveness.


Class: PerformanceObserver

A PerformanceObserver is a way to track and observe performance metrics in your Node.js application. It allows you to collect data about specific performance events, such as how long it takes to load a page or execute a function.

Creating a PerformanceObserver

To create a PerformanceObserver, you use the new PerformanceObserver() constructor. You can then pass a callback function to the constructor, which will be called whenever the observed performance events occur.

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log(entry.name, entry.duration);
  }
});

The callback function will be passed a PerformanceObserverEntryList object, which contains a list of PerformanceObserverEntry objects. Each entry represents a specific performance event that occurred.

Observing Performance Events

Once you have created a PerformanceObserver, you need to observe the specific performance events that you are interested in. You can do this by calling the observe() method on the observer object and passing in an array of event names.

observer.observe({ entryTypes: ["longtask"] });

The entryTypes array can contain any of the following event types:

  • longtask - A long-running task that takes longer than 50ms to execute.

  • resource - A resource that is loaded from the network.

  • mark - A custom mark that you can create to track a specific point in time.

  • measure - A custom measure that you can create to track the duration between two marks.

Real-World Applications

PerformanceObserver can be used to track and improve the performance of your Node.js applications. For example, you can use it to:

  • Identify long-running tasks that are causing performance problems.

  • Track the loading time of resources from the network.

  • Measure the duration of specific functions or code blocks.

By tracking and analyzing performance data, you can identify areas for improvement and optimize your code to improve the overall performance of your application.


PerformanceObserver.supportedEntryTypes

Description:

Lists all the performance entry types that are supported by the browser. A performance entry provides data about a specific event that happened during the page's lifetime.

Usage:

const observer = new PerformanceObserver((entryList) => {
  entryList.getEntries().forEach((entry) => {
    console.log(entry.entryType);
  });
});

observer.observe({ entryTypes: ["navigation"] });

In this example, a performance observer is created to monitor the "navigation" entry type. When a navigation event occurs, the entryType property of the performance entry will be logged to the console.

Supported Entry Types:

The list of supported entry types varies depending on the browser. Some common types include:

  • Resource: Contains data about a resource that was fetched by the browser, such as an image or script.

  • Navigation: Contains data about the navigation between different pages.

  • Paint: Contains data about when and how the browser painted the page.

  • Measure: Contains data about custom measurements that were recorded by the developer.

Applications:

PerformanceObserver.supportedEntryTypes can be used to:

  • Determine which performance metrics are available for monitoring.

  • Create performance observers to monitor specific events.

  • Gain insights into the performance of a web page by analyzing the collected performance entries.


PerformanceObserver

What is it?

  • A class observer that allows you to track and monitor performance events in your Node.js application.

How does it work?

  • You create a PerformanceObserver object and pass it a callback function.

  • The callback function will be invoked whenever a new performance event occurs.

  • You can specify the types of performance events you want to track using the entryTypes option.

Benefits:

  • Allows you to monitor the performance of your application and identify bottlenecks.

  • Can be used to track specific events, such as when a particular function is called or a certain metric is exceeded.

  • Helps you improve the performance of your application by providing detailed information about where and why it's slow.

Code Example:

const { performance, PerformanceObserver } = require("node:perf_hooks");

// Create a new PerformanceObserver object
const obs = new PerformanceObserver((list, observer) => {
  console.log(list.getEntries());

  // Stop observing after the first event
  performance.clearMarks();
  performance.clearMeasures();
  observer.disconnect();
});

// Start observing performance events of type 'mark'
obs.observe({ entryTypes: ["mark"] });

// Create a performance mark
performance.mark("test");

Real-World Applications

1. Tracking Function Call Performance

  • Create a PerformanceObserver to track the duration of specific function calls.

  • Use this information to identify slow functions and optimize them for better performance.

2. Monitoring Event Loop Latency

  • Create a PerformanceObserver to track the time spent in the event loop.

  • Use this information to detect potential bottlenecks caused by long-running tasks or excessive I/O operations.

3. Analyzing HTTP Request Performance

  • Create a PerformanceObserver to track the duration of HTTP requests.

  • Use this information to identify slow requests and optimize your server code or network infrastructure.

4. Debugging Application Slowdowns

  • Create a PerformanceObserver to track performance events during a period of slow performance.

  • Analyze the collected data to identify the root cause of the slowdown and implement fixes.

5. Benchmarking and Performance Comparisons

  • Create PerformanceObserver objects to track performance metrics between different versions of your application or different configurations.

  • Use the collected data to compare performance and identify areas for improvement.

Remember:

  • Use PerformanceObserver sparingly, as it can introduce overhead and slow down your application.

  • Clean up observers by disconnecting them when they are no longer needed to avoid memory leaks.


What is a PerformanceObserver?

A PerformanceObserver is a way to track performance metrics in Node.js. It allows you to monitor specific events, such as HTTP requests or function calls, and collect data about their performance.

What is performanceObserver.disconnect()?

The performanceObserver.disconnect() method lets you stop monitoring a specific event. This is useful if you no longer need to collect data about the event or if you want to free up resources.

How to use performanceObserver.disconnect()?

To use the performanceObserver.disconnect() method, you first need to create a PerformanceObserver instance. You can do this by calling the performance.observer() function:

const observer = performance.observer("http");

Once you have created a PerformanceObserver instance, you can start monitoring a specific event by calling the observe() method. For example, to monitor HTTP requests, you would call:

observer.observe({ entryTypes: ["resource"] });

To stop monitoring the event, you can call the performanceObserver.disconnect() method:

observer.disconnect();

Real-world use case

One potential use case for performanceObserver.disconnect() is in a web application where you want to track the performance of specific pages. You could create a PerformanceObserver instance to monitor the time it takes for the page to load and then disconnect the observer once the page is fully loaded. This would allow you to collect data about the page's performance without continuing to monitor it after it is no longer needed.


What is a PerformanceObserver?

A PerformanceObserver is a way to listen for events related to the performance of your code. When you create a PerformanceObserver, you specify the types of events you're interested in. The observer will then call a callback function every time one of those events occurs.

How to Use a PerformanceObserver

To use a PerformanceObserver, you first need to create one. You can do this by calling the PerformanceObserver constructor. The constructor takes a callback function as its first argument. This function will be called every time an event occurs that the observer is interested in.

The second argument to the PerformanceObserver constructor is an object that specifies the types of events you're interested in. You can specify a single type of event, or you can specify an array of types.

Example

The following example creates a PerformanceObserver that listens for all mark events:

const { performance, PerformanceObserver } = require("node:perf_hooks");

const observer = new PerformanceObserver((list) => {
  // The 'list' variable contains a list of all the mark events that have occurred since the observer was created.
});

observer.observe({ entryTypes: ["mark"] });

performance.mark("start");
performance.mark("end");

// The 'observer' callback will be called with a list containing two mark events: one for 'start' and one for 'end'.

Potential Applications

PerformanceObservers can be used to track the performance of your code in a variety of ways. For example, you could use a PerformanceObserver to:

  • Identify performance bottlenecks in your code.

  • Track the performance of your code over time.

  • Compare the performance of different versions of your code.

Real-World Example

One real-world example of how PerformanceObservers can be used is in the Chrome DevTools. The Chrome DevTools uses PerformanceObservers to track the performance of the web page being inspected. This information is then used to provide insights into the page's performance and to identify areas where the page can be improved.


PerformanceObserverEntryList

Simplified Definition:

It's like a box that collects performance events whenever you request it using the performance.observe function.

Detailed Explanation:

  • The PerformanceObserverEntryList class stores lists of PerformanceEntry objects.

  • PerformanceEntry objects contain information about specific performance events, like page load time or script execution time.

  • To create a PerformanceObserverEntryList, you don't call it directly. Instead, you use the performance.observe function, which gives you a PerformanceObserver object.

  • The PerformanceObserver object has a takeRecords method that returns a PerformanceObserverEntryList containing the performance events that have occurred since the last time you called takeRecords.

Real-World Implementation:

// Create a PerformanceObserver
const observer = new PerformanceObserver((list) => {
  // Get the list of performance entries
  const entries = list.getEntries();

  // Process the performance entries
  entries.forEach((entry) => {
    console.log(entry.name, entry.startTime, entry.duration);
  });
});

// Start observing performance events
observer.observe({ entryTypes: ["longtask"] });

// Wait for a while to collect performance events
setTimeout(() => {
  // Stop observing performance events
  observer.disconnect();
}, 1000);

Potential Applications:

  • Analyzing page load performance

  • Identifying performance bottlenecks

  • Optimizing script execution time

  • Tracking long-running tasks


performanceObserverEntryList.getEntries()

Simplified Explanation:

Imagine you have a list of events recorded by your computer's timer. Each event has a name, a type (like "mark" or "measure"), and a time. performanceObserverEntryList.getEntries() returns all these events in order based on when they happened.

Example:

const performance = require("node:perf_hooks");

// Create a list to store performance entries
const performanceEntries = [];

// Create an observer to listen for performance entries
const observer = new PerformanceObserver((list, obs) => {
  // Add the entries to our list
  performanceEntries.push(...list.getEntries());

  // Stop listening for more entries
  obs.disconnect();
});

// Start listening for performance entries
observer.observe({ type: "mark" });

// Mark two performance entries with names "test" and "meow"
performance.mark("test");
performance.mark("meow");

// Print the performance entries
console.log(performanceEntries);

/*
Output:
[
  PerformanceEntry {
    name: 'test',
    entryType: 'mark',
    startTime: 81.465639,
    duration: 0,
    detail: null
  },
  PerformanceEntry {
    name: 'meow',
    entryType: 'mark',
    startTime: 81.860064,
    duration: 0,
    detail: null
  }
]
*/

Potential Applications:

  • Profiling code: Identifying bottlenecks and optimizing performance.

  • Performance testing: Measuring website or application performance and identifying areas for improvement.

  • Debugging memory leaks: Identifying objects that are not being released, causing memory issues.


performanceObserverEntryList.getEntriesByName(name[, type])

  • What is it?

    • A method that returns a list of performance entries with a specific name and optionally a specific type.

  • Parameters:

    • name: The name of the performance entries to return.

    • type: The type of the performance entries to return (optional).

  • Returns:

    • An array of PerformanceEntry objects.

  • Example:

    const { performance, PerformanceObserver } = require("node:perf_hooks");
    
    const obs = new PerformanceObserver((perfObserverList, observer) => {
      console.log(perfObserverList.getEntriesByName("meow"));
      // Output: []
    
      performance.mark("meow");
    
      console.log(perfObserverList.getEntriesByName("meow"));
      // Output: [PerformanceEntry { ... }]
    });
    obs.observe({ entryTypes: ["mark"] });
  • Real-world application:

    • Monitoring the performance of specific events in your application, such as API calls or database queries.

  • Simplified explanation:

    • Imagine you have a list of performance entries, like a list of all the times your application has done something specific, like made an API call or rendered a page.

    • The getEntriesByName method lets you filter that list to only include the entries with a specific name, like "API call."

    • You can optionally also filter by the type of entry, like "mark" or "measure."

    • This can be useful for debugging performance issues or tracking the performance of specific parts of your application.


performanceObserverEntryList.getEntriesByType(type)

Simplified Explanation

Imagine you have a list of performance entries that track events like marking a point in time or measuring the duration between two marks. The getEntriesByType method lets you filter this list to include only entries of a specific type.

Detailed Explanation

  • Type: Specifies the type of performance entry you want to filter for. It can be "mark", "measure", "counter", or "resource".

Return Value

  • An array of PerformanceEntry objects that match the specified type, sorted in chronological order based on their startTime property.

Code Example

// Create a performance observer
const obs = new PerformanceObserver((list) => {
  // Get all mark entries
  const marks = list.getEntriesByType("mark");

  // Log the names of the marks
  for (const mark of marks) {
    console.log(mark.name);
  }
});

// Start observing performance entries
obs.observe({ type: "mark" });

// Create some marks
performance.mark("start");
performance.mark("end");

// Stop observing performance entries
obs.disconnect();

Output

start
end

Real-World Applications

  • Performance Monitoring: Filter performance entries by type to track specific metrics, such as the time it takes for a page to load (type: "measure") or the number of DOM elements on a page (type: "counter").

  • Resource Optimization: Filter performance entries by type to identify resource-intensive assets, such as images or scripts, that may be slowing down the page.

  • Benchmarking: Filter performance entries by type to compare the performance of different algorithms or code optimizations.


perf_hooks.createHistogram([options])

Simplified Explanation:

Perf Hooks Histogram is a tool that helps you measure how often things happen within a specific range of values. It's like a graph where the X-axis is the range of values, and the Y-axis is how many times each value occurred.

Detailed Explanation:

Options:

  • lowest: The lowest value that the histogram can measure. This must be a positive integer greater than 0.

  • highest: The highest value that the histogram can measure. This must be an integer that is at least twice the lowest value.

  • figures: The number of decimal places to show in the results. This must be between 1 and 5.

Example:

const { performance } = require("perf_hooks");

// Create a Perf Hooks Histogram with the following options:
// - Lowest value: 1
// - Highest value: 100
// - Number of decimal places: 3
const histogram = performance.createHistogram({
  lowest: 1,
  highest: 100,
  figures: 3,
});

// Record some values into the histogram
histogram.record(10);
histogram.record(20);
histogram.record(30);

// Get the results of the histogram
const results = histogram.export();

// The results will look something like this:
// {
//   lowest: 1,
//   highest: 100,
//   figures: 3,
//   mean: 20,
//   stddev: 10,
//   buckets: [
//     {
//       start: 1,
//       end: 10,
//       count: 1,
//     },
//     {
//       start: 10,
//       end: 20,
//       count: 1,
//     },
//     {
//       start: 20,
//       end: 30,
//       count: 1,
//     },
//   ],
// }

Real-World Applications:

Perf Hooks Histograms can be used to measure things like:

  • The distribution of response times for a web server

  • The size of files being uploaded to a website

  • The duration of time it takes to complete a task

  • The number of errors that occur during a process


Simplified Node.js perf_hooks.monitorEventLoopDelay()

Overview

The perf_hooks.monitorEventLoopDelay function measures how much time the event loop in Node.js takes to execute tasks. It does this by setting up a timer that checks how much time it takes for the loop to finish its current task.

Options

You can customize the timer's settings with an options object, which has one property:

  • resolution: The interval (in milliseconds) at which the timer checks for delays. The default is 10 milliseconds.

Usage

To use monitorEventLoopDelay, call it like this:

const { monitorEventLoopDelay } = require("node:perf_hooks");

const h = monitorEventLoopDelay({ resolution: 20 });

This creates an IntervalHistogram object, which stores information about the delays it has measured.

Getting Results

Once you have enabled the timer by calling h.enable(), it starts collecting data. To get the results, call h.disable(). After that, you can access properties like:

  • min: The minimum measured delay.

  • max: The maximum measured delay.

  • mean: The average measured delay.

  • stddev: The standard deviation of the measured delays.

  • percentiles: An array of percentiles of the measured delays.

  • percentile(x): The x-th percentile of the measured delays.

Real-World Applications

monitorEventLoopDelay can be helpful in diagnosing performance problems in your Node.js applications. For example, it can help you find out if the event loop is getting blocked by long-running tasks.

Here's a complete example:

const { monitorEventLoopDelay } = require("node:perf_hooks");

const h = monitorEventLoopDelay({ resolution: 20 });

h.enable();

// Do some work that might cause event loop delays.

h.disable();

console.log(h.min);
console.log(h.max);
console.log(h.mean);

This code measures the event loop delays while the application is doing work, and then prints out the results.

Conclusion

perf_hooks.monitorEventLoopDelay is a useful tool for measuring event loop performance in Node.js. It can help you identify if long-running tasks are blocking the event loop and causing performance issues.


Class: Histogram

The Histogram class represents a histogram of recorded values. Histograms are useful for recording the distribution of recorded values, such as the duration of function calls or the size of heap allocations.

Constructor

The Histogram constructor takes the following arguments:

  • name (string): The name of the histogram.

  • buckets (array): An array of bucket boundaries. The first bucket is always [0, buckets[0]), the last bucket is always [buckets[buckets.length - 1], infinity).

// Create a histogram with 5 buckets:
//
//   - [0, 100)
//   - [100, 200)
//   - [200, 300)
//   - [300, 400)
//   - [400, infinity)
//
const histogram = new perf_hooks.Histogram('my_histogram', [100, 200, 300, 400]);

Methods

The Histogram class has the following methods:

  • record(value) (void): Records a value in the histogram.

  • export() (object): Returns an object with the following properties:

    • name (string): The name of the histogram.

    • buckets (array): An array of bucket boundaries.

    • counts (array): An array of the number of values that fell into each bucket.

    • min (number): The minimum value that was recorded in the histogram.

    • max (number): The maximum value that was recorded in the histogram.

    • mean (number): The mean value of the values that were recorded in the histogram.

    • stddev (number): The standard deviation of the values that were recorded in the histogram.

// Record some values in the histogram.
histogram.record(10);
histogram.record(200);
histogram.record(400);

// Print the histogram data.
console.log(histogram.export());

Applications

Histograms can be used to:

  • Find the distribution of values for a particular metric.

  • Identify outliers in a data set.

  • Monitor the performance of a system over time.

For example, a histogram can be used to track the distribution of response times for a web server. This information can be used to identify performance bottlenecks and to improve the server's performance.


Histogram.count

The histogram.count property in perf_hooks returns the number of samples recorded by the histogram. Increments with each execution of the record() method.


histogram.countBigInt

  • {bigint}

The number of samples recorded by the histogram.

Simplified Explanation

The histogram.countBigInt property tells you how many values have been recorded in the histogram. It is a count of the number of samples that have been added to the histogram.

Code Snippet

const { performance } = require("perf_hooks");

const histogram = performance.timeline.histogram();

// Add some samples to the histogram
histogram.recordValue(10);
histogram.recordValue(20);
histogram.recordValue(30);

// Get the count of samples
const count = histogram.countBigInt;

console.log(count); // 3

Real World Applications

The histogram.countBigInt property can be used to track the number of samples that have been recorded in a histogram. This can be useful for debugging or for understanding how the histogram is being used.


histogram.exceeds

  • {number}

The number of times the event loop delay exceeded the maximum 1 hour event loop delay threshold.

Simplified Explanation:

The histogram.exceeds property tells us how many times the time it took to complete all the tasks in the event loop exceeded the maximum allowed time of 1 hour.

Real World Example:

Let's say you have a web server that is handling requests from users. Each request is added to the event loop, and the server processes them in the order they were received. If the server is overloaded with requests, it may take more than 1 hour to process them all. In this case, the event loop delay would exceed the maximum threshold, and the histogram.exceeds property will increment.

Potential Applications:

  • Monitoring the performance of your application to identify potential bottlenecks.

  • Identifying and fixing issues that cause high event loop delays.


Histogram.exceedsBigInt

Explanation:

Imagine your computer as a stage where actors (events) perform one after another. The event loop is the manager who makes sure the actors perform in the right order.

The histogram.exceedsBigInt tells you how many times the event loop took too long to finish an actor's performance (event). Too long means more than one hour!

Simplified Explanation:

It's like a countdown clock for the event loop. If it goes over the 1-hour mark too often, it means the event loop is having trouble keeping up with the show.

Real-World Application:

This information can help you debug performance issues in your code. If you see a high count in this metric, it could be a sign that your code is causing the event loop to get bogged down.

Code Example:

const { performance } = require("perf_hooks");

// Start measuring the event loop delay
performance.mark("start");

// Do something that takes a long time
for (let i = 0; i < 1000000000; i++) {
  // Do nothing
}

// Stop measuring the event loop delay
performance.mark("end");

// Get the event loop delay
const delay = performance.measure("start", "end").duration;

// Check if the event loop delay exceeded the maximum threshold
if (delay > 3600000) {
  console.log("Event loop delay exceeded the maximum threshold!");
}

Simplified Explanation:

The histogram.max property represents the longest observed delay in executing a single event loop iteration.

Real-World Example:

Imagine you have a website that runs on a web server. When users visit the website, the web server creates an event loop. This event loop continuously checks for incoming requests, processes them, and sends responses back to the users.

The histogram.max property tells you how long the longest delay was between the time the web server received a request and the time it sent back the response. If this value is too high, it means that your website is taking too long to respond to users, which can negatively impact their experience.

Potential Applications:

  • Identifying performance bottlenecks in your code

  • Optimizing your code to reduce event loop delays

  • Monitoring the health of your web server


Histogram.maxBigInt

Imagine your computer's event loop as a race car driver. The histogram.maxBigInt tells you the longest time it took for the driver to make a lap.

Simplified Explanation:

The histogram.maxBigInt is the longest time it took for your computer to complete a loop (a cycle of running through all the tasks in its queue).

Real-World Example:

Let's say you're running a web server. If the histogram.maxBigInt is too high, it means your server is taking too long to respond to user requests. That can make users frustrated and cause them to leave.

Potential Applications:

  • Performance Tuning: Identifying bottlenecks in your code or system.

  • User Experience Analytics: Tracking how long it takes for your app or website to load or respond to user actions.

  • Capacity Planning: Determining how many users your server can handle without overloading.

Code Implementation:

const { performance } = require("perf_hooks");

const obs = performance.observer((items) => {
  const eventLoopDelay = items[0].data;
  console.log(`Event loop delay: ${eventLoopDelay} ms`);
});

obs.observe({ entryTypes: ["event-loop"] });

histogram.mean

  • {number}

This property represents the average of the recorded event loop delays. It provides an overall measure of the event loop's performance. A higher value indicates longer delays and potentially slower event handling.

Example:

const { performance } = require("perf_hooks");

const obs = performance.eventLoopUtilization();

console.log(`Event loop mean delay: ${obs.mean} milliseconds`);

Real-World Application:

  • Monitoring Event Loop Performance: The mean property can be used to monitor the event loop's overall performance and identify any potential bottlenecks or inefficiencies.

  • Optimizing Event Loop Handling: By analyzing the mean value, developers can identify which processes or tasks are causing event loop delays and optimize their code accordingly. This can improve the responsiveness and overall efficiency of the application.


histogram.min

  • Meaning: The shortest delay observed in the event loop.

  • Real-World Example: If your event loop processes events 10 times per second, the histogram.min would be 100 milliseconds.

  • Simplified Explanation: It's like the fastest time it took to complete a single event loop iteration.

Complete Code Example:

const { performance } = require("perf_hooks");

// Start the event loop
performance.mark("start");

// Do some work
setTimeout(() => {
  performance.mark("end");
}, 100);

// Calculate the event loop delay
const delay = performance.measure("delay", "start", "end");
console.log(`Event loop delay: ${delay.duration} ms`);
console.log(`Minimum delay: ${performance.eventLoopHistogram.min} ms`);

Potential Applications:

  • Identifying performance bottlenecks in event-driven applications.

  • Optimizing event loop execution to improve responsiveness and performance.


What is histogram.minBigInt?

histogram.minBigInt is a property of the histogram object in the perf_hooks module. It represents the lowest recorded delay, in nanoseconds, between two consecutive events in the event loop.

Simplified Explanation:

Imagine the event loop as a machine that runs different tasks one after the other. The delay between the end of one task and the start of the next is called the "event loop delay". histogram.minBigInt stores the smallest delay that has been recorded.

Code Example:

const { performance } = require("perf_hooks");
const obs = performance.observer("event-loop-delay", (list) => {
  list.getEntries().forEach((entry) => {
    console.log(`Minimum delay: ${entry.minBigInt} nanoseconds`);
  });
});

obs.enable();

Real-World Applications:

  • Monitoring the performance of the event loop to identify potential bottlenecks or slowdowns.

  • Optimizing code to reduce event loop delays and improve overall application responsiveness.

  • Debugging performance issues related to the event loop, such as delays caused by long-running tasks or excessive task queues.


Simplified Explanation:

Imagine a histogram as a graph showing how often different values occur. The percentile is a way to find the value below which a certain percentage of the data falls.

Example:

Let's say we have a histogram of exam scores:

[20, 25, 30, 35, 40, 45]

The 25th percentile would be the value below which 25% of the scores fall. In this case, we can see that 20, 25, and 30 fall below the 25th percentile because they represent the first 25% of the data. Therefore, the 25th percentile is 30.

Real-World Application:

Businesses can use percentiles to analyze customer performance. For example, a website might calculate the 95th percentile of load times to determine the maximum acceptable time for 95% of page loads.

Code Example:

const perfHooks = require("perf_hooks");
const histogram = new perfHooks.Histogram();

// Add data to the histogram
for (let i = 0; i < 100; i++) {
  histogram.update(Math.random() * 100);
}

// Get the 25th percentile
const p25 = histogram.percentile(25);

console.log(`The 25th percentile is ${p25}`);

Output:

The 25th percentile is 24.999294292509994

Histogram.percentileBigInt()

Simplified Explanation:

Consider a histogram as a bucket of data sorted into different ranges, like a bar graph. Let's say you have a histogram of the heights of people in a room. Each bar represents a range of heights, such as 5-6 feet, 6-7 feet, and so on.

The percentileBigInt() method allows you to find the height at a specific percentile. For example, if you pass in 50, it will return the height that divides the data into two equal halves. Half the people in the room are shorter than this height, and the other half are taller.

Code Example:

const histogram = new Histogram();

// Add heights to the histogram
histogram.addValue(65);
histogram.addValue(68);
histogram.addValue(70);
histogram.addValue(72);
histogram.addValue(74);

// Find the height at the 50th percentile
const medianHeight = histogram.percentileBigInt(50);

console.log(`Median height: ${medianHeight}`); // Output: Median height: 70

Real-World Applications:

  • Data analysis: Finding the median value of a dataset can provide insights into the distribution of data.

  • Performance monitoring: Measuring the 95th percentile of response times can indicate the worst-case performance of a system.

  • Risk assessment: Calculating the 1st percentile of a set of financial losses can help determine the minimum amount of risk that needs to be covered.


histogram.percentiles

  • {Map}

Returns a Map object detailing the accumulated percentile distribution.

Simplified Explanation:

This property provides a map that shows the distribution of values in the histogram. Each key in the map represents a percentile, and the corresponding value is the value at that percentile. For example, a key of 0.5 would represent the median value, while a key of 0.99 would represent the 99th percentile.

Code Example:

const histogram = new perf_hooks.Histogram();

histogram.update(10);
histogram.update(20);
histogram.update(30);

const percentiles = histogram.percentiles();

console.log(percentiles);
// {
//   '0.5': 20,
//   '0.99': 30
// }

Real World Applications:

  • Analyzing the performance of a web application by tracking the response times of requests and identifying the percentiles of slow responses.

  • Identifying bottlenecks in a system by examining the distribution of values in a histogram and pinpointing the percentiles where most of the delays occur.

  • Monitoring the health of a system by tracking the percentiles of key performance metrics over time and identifying any significant changes.


histogram.percentilesBigInt

  • {Map}

This method returns a Map object that provides a breakdown of the accumulated percentile distribution for the histogram. Each key in the map represents a percentile, while the corresponding value represents the cumulative count at that percentile.

Example:

const histogram = new Histogram();
histogram.recordValue(10);
histogram.recordValue(20);
histogram.recordValue(30);
const percentiles = histogram.percentilesBigInt();
console.log(percentiles); // { '50th': 20n, '100th': 30n }

In the example above, the histogram has recorded three values. The percentiles map returned by the percentilesBigInt() method shows that the 50th percentile is 20 and the 100th percentile is 30. This indicates that half of the recorded values are less than or equal to 20, and all of the recorded values are less than or equal to 30.

Real-World Application:

This method can be used to analyze the distribution of a set of data. For example, it can be used to determine the median or the 90th percentile of a set of values. It can also be used to identify outliers in a data set.


histogram.reset()

Resets the collected histogram data.

Simplified Explanation:

Imagine you have a box of toys. You want to track how many toys of each type you have so you create a histogram. As you add toys to the box, the histogram keeps track of the count for each type. If you want to start counting from scratch, you can "reset" the histogram, which will erase all the previous counts.

// Create a histogram
const histogram = new Histogram();

// Add some toys to the box
histogram.recordValue(10);
histogram.recordValue(10);
histogram.recordValue(20);

// Reset the histogram
histogram.reset();

// Now the histogram is empty again
console.log(histogram.getCount(10)); // 0
console.log(histogram.getCount(20)); // 0

Potential Applications:

  • Performance monitoring: Resetting the histogram can be useful for periodic monitoring of performance metrics, allowing you to track changes and identify performance bottlenecks.

  • Data analysis: Resetting the histogram can help analyze data over different time periods, such as comparing performance before and after a code change.


histogram.stddev

  • {number}

The standard deviation of the recorded event loop delays. This value represents how spread out the data is. A low standard deviation means that the data is clustered closely around the mean, while a high standard deviation means that the data is more spread out.

Example:

const { performance } = require("perf_hooks");

// Create an event loop delay histogram.
const histogram = performance.eventLoopUtilization();

// Record some event loop delays.
setTimeout(() => {}, 10);
setTimeout(() => {}, 20);
setTimeout(() => {}, 30);

// Get the standard deviation of the recorded delays.
const stddev = histogram.stddev;

console.log(stddev); // 6.666666666666667

Applications:

The standard deviation of the event loop delays can be used to identify performance problems. A high standard deviation can indicate that the event loop is being overloaded, which can lead to lag and unresponsiveness.

By monitoring the standard deviation of the event loop delays, developers can identify and fix performance problems before they become noticeable to users.


Class: IntervalHistogram extends Histogram

An IntervalHistogram is like a regular Histogram, but it automatically updates itself at regular intervals. This can be useful for tracking metrics over time, such as the number of requests per second or the average response time.

Creating an IntervalHistogram

To create an IntervalHistogram, you can use the following code:

const { PerformanceObserver, metrics } = require('perf_hooks');

const histogram = new PerformanceObserver((items) => {
  items.getEntries().forEach((entry) => {
    console.log(`${entry.name}: ${entry.duration}`);
  });
});

histogram.observe({ entryTypes: ['measure'] });

This will create a histogram that will log the duration of all measure events that occur.

Using an IntervalHistogram

Once you have created an IntervalHistogram, you can use it to track metrics over time. To do this, you can use the getEntries() method to get the current values of the histogram.

For example, the following code will log the number of requests per second over the last 10 seconds:

const histogram = new PerformanceObserver((items) => {
  const entries = items.getEntries();
  const numRequests = entries[0].values[0].value;
  console.log(`Number of requests per second: ${numRequests}`);
});

histogram.observe({ entryTypes: ['measure'] });

This code will log the number of requests per second every second.

Potential Applications

  • Tracking the performance of a web application

  • Identifying bottlenecks in a system

  • Measuring the impact of changes to a system

  • Creating dashboards to visualize performance metrics


histogram.disable()

  • Purpose: Stops the histogram from collecting data.

  • Return Value: true if the histogram was successfully disabled, false if it was already disabled.

Example:

const { Histogram } = require("perf_hooks");

const histogram = new Histogram();

// Start the histogram.
histogram.enable();

// Collect some data.
for (let i = 0; i < 100000; i++) {
  histogram.record(Math.random());
}

// Disable the histogram.
const disabled = histogram.disable();

// Confirm that the histogram is disabled.
console.log(histogram.enabled); // false

Potential Applications:

  • Measuring the performance of a function by recording the time it takes to execute and then disabling the histogram to stop collecting data.

  • Monitoring the performance of a system by collecting data on a regular basis and then disabling the histogram when the data is no longer needed.


histogram.enable()

  • Returns: {boolean}

Enables the update interval timer. Returns true if the timer was started, false if it was already started.

Simplified Explanation:

Imagine you have a stopwatch that you use to measure the duration of certain tasks. When you start the stopwatch, it begins to keep track of the time. If you try to start it again while it's already running, nothing happens.

The histogram.enable() function is like that stopwatch. If you call it while the timer is already running, nothing happens and it returns false. But if you call it when the timer is stopped, it starts the timer and returns true.

Real-World Code Implementation:

// Start a histogram timer
const histogram = new perf_hooks.Histogram();
histogram.enable();

// Stop the timer after some time
setTimeout(() => {
  histogram.disable();
}, 500);

// Get the histogram data
const data = histogram.toJSON();
console.log(data);

Potential Applications:

  • Measuring the performance of different code paths

  • Identifying bottlenecks in applications

  • Profiling the performance of microservices


Cloning an IntervalHistogram

Simplified Explanation:

Imagine you have a histogram that tracks data over time. You want to share this histogram with another process in your computer. To do this, you can "clone" the histogram and send it to the other process.

Detailed Explanation:

  • IntervalHistogram: A type of histogram that tracks data over time intervals.

  • MessagePort: A way to communicate between different processes in a computer.

  • Cloning: Creating a copy of an object.

  • Plain Histogram: A histogram that does not have the ability to enable or disable data collection.

Code Snippet:

// Process 1 (Sending the histogram)
const port = new MessagePort();
port.postMessage(histogram.clone());

// Process 2 (Receiving the histogram)
port.onmessage = (event) => {
  const clonedHistogram = event.data;
  // Use the cloned histogram as a regular histogram
};

Real-World Applications:

  • Sharing performance data between different components of a large application.

  • Collecting and analyzing performance metrics from multiple devices in a distributed system.

Potential Applications:

  • Performance monitoring: Tracking and visualizing the performance of a web application or server.

  • Resource utilization: Monitoring the usage of resources such as memory and CPU.

  • Benchmarking: Comparing the performance of different software or hardware configurations.


Simplified Explanation

Class: RecordableHistogram

A RecordableHistogram is a type of histogram that allows you to record the frequency of different events. It's like a tally counter, but it keeps track of multiple events instead of just one.

How it Works

Imagine you have a store and you want to track the number of people who buy different products. You can create a RecordableHistogram for each product, and then increment the count in each histogram whenever someone buys that product.

For example:

const bananasHistogram = new RecordableHistogram();
const applesHistogram = new RecordableHistogram();
const orangesHistogram = new RecordableHistogram();

// When someone buys bananas, increment the bananas histogram
bananasHistogram.record(1);

// When someone buys apples, increment the apples histogram
applesHistogram.record(1);

// When someone buys oranges, increment the oranges histogram
orangesHistogram.record(1);

Now, you can use the histograms to see how many people have bought each product.

console.log(`Bananas: ${bananasHistogram.getMean()}`);
console.log(`Apples: ${applesHistogram.getMean()}`);
console.log(`Oranges: ${orangesHistogram.getMean()}`);

Potential Applications

RecordableHistograms can be used in a variety of applications, including:

  • Tracking website traffic

  • Analyzing user behavior

  • Improving performance

  • Identifying bottlenecks

Real-World Example

Let's say you have a website and you want to track how many people visit each page. You can create a RecordableHistogram for each page, and then increment the count each time someone visits that page.

This information can help you identify which pages are most popular and which pages need improvement. You can also use it to track changes in traffic over time.


histogram.add(other)

  • other {RecordableHistogram}

Adds the values from other to this histogram.

Simplified Explanation:

Imagine you have two histograms that track the distribution of recorded values. The histogram.add() function allows you to combine these two histograms into one, effectively adding the recorded values from both histograms together.

Example:

const histogram1 = new perf_hooks.Histogram();
histogram1.record(10);
histogram1.record(20);

const histogram2 = new perf_hooks.Histogram();
histogram2.record(5);
histogram2.record(15);

histogram1.add(histogram2);

// Histogram 1 now contains the values: [5, 10, 15, 20]

Real-World Application:

This function can be used to combine data from different sources or time periods into a single histogram. For example, if you have two histograms that track the latency of API requests from different servers, you can use histogram.add() to get a combined view of the latency distribution across all servers.


histogram.record(val)

The record method of the Histogram class records a new value in the histogram.

Parameters:

  • val {number|bigint} The amount to record in the histogram.

Returns:

  • {void}

Example:

const { Histogram } = require("perf_hooks");

const histogram = new Histogram();

histogram.record(100);
histogram.record(200);
histogram.record(300);

console.log(histogram.toJSON());

Output:

{
  "minimum": 100,
  "maximum": 300,
  "mean": 200,
  "standardDeviation": 100,
  "percentiles": [
    {
      "percentile": 0.25,
      "value": 100
    },
    {
      "percentile": 0.5,
      "value": 200
    },
    {
      "percentile": 0.75,
      "value": 300
    }
  ]
}

Real World Application:

Histograms can be used to collect and analyze data about the distribution of values. For example, a web server could use a histogram to track the response times of its requests. This data could then be used to identify performance bottlenecks and improve the server's performance.


histogram.recordDelta()

Explanation:

histogram.recordDelta() is a function in Node.js that measures how long it takes for a specific event to happen. It's like a stopwatch that starts when you call the function for the first time, and stops when you call it again. The difference between the two times is recorded in a "histogram," which is like a chart that shows how often different time durations happen.

Simplified Analogy:

Imagine you're baking a cake. You start the timer when you put the cake in the oven. When the cake is done, you stop the timer. The time on the timer is how long it took the cake to bake. You can use histogram.recordDelta() to measure how long it takes to bake different kinds of cakes, or how long it takes to do other tasks, like loading a website or processing data.

Code Example:

const { Histogram } = require("perf_hooks");

// Create a histogram to measure the time it takes to load a webpage
const histogram = new Histogram();

// Start the timer when the webpage starts loading
histogram.start();

// Stop the timer when the webpage finishes loading
histogram.stop();

// Get the time it took to load the webpage
const time = histogram.getDuration();

console.log(`The webpage loaded in ${time} nanoseconds`);

Real-World Applications:

  • Performance Optimization:

    • Identifying performance bottlenecks in applications by measuring how long different tasks take.

  • System Monitoring:

    • Tracking system resources like CPU and memory usage over time using histograms.

  • Bug Identification:

    • Detecting performance issues or bugs by comparing histograms of expected and actual behavior.


Performance Hooks: Measuring Execution Time and Performance

1. What are Performance Hooks?

Imagine you're baking a chocolate cake. You want to know how long each step takes: mixing ingredients, baking, and cooling. Performance hooks are like little alarms that help you measure these time intervals.

2. How do Performance Hooks Work?

You sprinkle performance hooks at specific points in your code, and they automatically record when these points are reached. You can then retrieve the time since each hook was fired.

3. Types of Performance Hooks:

  • Histogram Hooks: Measure the distribution of execution times.

  • PerformanceObserver: A central hub for subscribing to events from all performance hooks.

  • Duration Hook: Measures the time between two events.

  • Immediate Hook: Triggers immediately when the hook is instantiated.

Code Example (Histogram Hook):

const { performance } = require("perf_hooks");

// Start measuring
const measuringStartTime = performance.now();

// Do the task
console.log("Hello, world!");

// Stop measuring
const measuringEndTime = performance.now();

// Get the duration
console.log(`The execution took ${measuringEndTime - measuringStartTime} ms`);

4. Real-World Applications:

  • Performance Monitoring: Track website performance and identify bottlenecks.

  • Optimization: Optimize code by identifying slow functions or loops.

  • Profiling: Analyze the performance of specific code blocks or user interactions.

  • Error Handling: Detect performance issues that may contribute to errors.

Additional Notes:

  • Performance hooks provide high-resolution timing measurements.

  • They can be used in Node.js applications and Chrome DevTools.

  • Consider using third-party libraries like "perf-metrics" for more advanced performance analysis.


Measuring the Duration of Async Operations

Overview

When you run an asynchronous operation in Node.js, such as a setTimeout() call, the JavaScript engine doesn't wait for the operation to complete before moving on to other tasks. This can make it difficult to measure the actual duration of the operation.

The Async Hooks and Performance APIs in Node.js provide a way to accurately measure the duration of async operations, including the time spent executing their callbacks.

Async Hooks

Async Hooks allow you to hook into the Node.js event loop and track the creation and destruction of asynchronous resources. This includes resources like timers, file system operations, and even HTTP requests.

For example, the following code uses Async Hooks to track the creation and destruction of a setTimeout() operation:

const async_hooks = require("node:async_hooks");

const hook = async_hooks.createHook({
  init(id, type) {
    if (type === "Timeout") {
      console.log(`Timeout ${id} created.`);
    }
  },
  destroy(id) {
    if (type === "Timeout") {
      console.log(`Timeout ${id} destroyed.`);
    }
  },
});

hook.enable();

setTimeout(() => {
  console.log("Timeout callback executed.");
}, 1000);

Performance API

The Performance API provides a way to measure the performance of your Node.js application. This includes functions for creating and measuring performance marks and measures.

For example, the following code uses the Performance API to measure the duration of a setTimeout() operation:

const { performance } = require("node:perf_hooks");

const startTime = performance.now();

setTimeout(() => {
  const endTime = performance.now();
  console.log(`Timeout took ${endTime - startTime} milliseconds to execute.`);
}, 1000);

Combining Async Hooks and Performance API

You can combine Async Hooks and the Performance API to measure the duration of async operations, including the time spent executing their callbacks.

For example, the following code uses Async Hooks to track the creation and destruction of a setTimeout() operation, and the Performance API to measure its duration:

const async_hooks = require("node:async_hooks");
const { performance } = require("node:perf_hooks");

const set = new Set();
const hook = async_hooks.createHook({
  init(id, type) {
    if (type === "Timeout") {
      performance.mark(`Timeout-${id}-Init`);
      set.add(id);
    }
  },
  destroy(id) {
    if (set.has(id)) {
      set.delete(id);
      performance.mark(`Timeout-${id}-Destroy`);
      performance.measure(
        `Timeout-${id}`,
        `Timeout-${id}-Init`,
        `Timeout-${id}-Destroy`
      );

      const duration = performance.getEntriesByName(`Timeout-${id}`)[0]
        .duration;
      console.log(`Timeout ${id} took ${duration} milliseconds to execute.`);
    }
  },
});

hook.enable();

setTimeout(() => {}, 1000);

Real-World Applications

Measuring the duration of async operations can be useful in a number of real-world applications, such as:

  • Performance optimization: By measuring the duration of async operations, you can identify bottlenecks and optimize their performance.

  • Debugging: Measuring the duration of async operations can help you debug issues such as unexpected delays or deadlocks.

  • Testing: Measuring the duration of async operations can help you verify the performance of your application under different conditions.


Measuring Load Times of Dependencies

Problem: It's often useful to know how long it takes to load dependencies (like other modules) in your Node.js application.

Solution: Use Node.js's perf_hooks module to measure the duration of require() operations.

How it Works:

  1. Monkey Patching require(): We create a custom version of require() that tracks the time it takes to load a dependency.

  2. Performance Observer: We use a Performance Observer to monitor when require() is called and record the duration.

Real-World Code Example:

const { performance, PerformanceObserver } = require("node:perf_hooks");
const mod = require("node:module");

// Monkey patch require()
mod.Module.prototype.require = performance.timerify(
  mod.Module.prototype.require
);
require = performance.timerify(require);

// Create Performance Observer
const obs = new PerformanceObserver((list) => {
  list.getEntries().forEach((entry) => {
    console.log(`require('${entry[0]}')`, entry.duration);
  });
  performance.clearMarks();
  performance.clearMeasures();
  obs.disconnect();
});
obs.observe({ entryTypes: ["function"], buffered: true });

require("some-module");

Output:

require('some-module') 12.345

Potential Applications:

  • Identify slow-loading dependencies.

  • Optimize application performance by reducing dependency load times.

  • Monitor the performance of your application over time.


Simplified Explanation

Measuring HTTP Round-Trip Time

We use a PerformanceObserver to measure how long it takes for an HTTP request to go from the client to the server and back.

HTTP Client (request):

  • Time start: When we start sending the request.

  • Time end: When we receive the response.

  • Round-trip time: Time end minus Time start.

HTTP Request (response):

  • Time start: When we receive the request.

  • Time end: When we send the response.

  • Round-trip time: Time end minus Time start.

Code Snippets

// Client
start = Date.now();
const request = http.get("http://example.com");
request.on("response", () => {
  end = Date.now();
  console.log(`Client round-trip time: ${end - start}ms`);
});

// Server
server.on("request", (req, res) => {
  start = Date.now();
  res.on("finish", () => {
    end = Date.now();
    console.log(`Server round-trip time: ${end - start}ms`);
  });
});

Real-World Applications

  • Latency monitoring: Track the time it takes for requests to travel between clients and servers.

  • Performance optimization: Identify bottlenecks and improve request response times.

  • Troubleshooting: Diagnose slow HTTP connections.


Measuring Performance of net.connect (TCP) Connections

Problem: You want to know how long it takes for a TCP connection to establish successfully.

Solution: Node.js' perf_hooks module provides a way to measure the performance of asynchronous operations, including TCP connections.

Explanation:

  1. PerformanceObserver: This is an object that allows you to observe the performance of specific events. In this case, we're interested in network events (net entry types).

  2. Observing Network Events: By calling observe(), we tell the PerformanceObserver to start collecting data on network events.

  3. net.connect Performance Entry: When a successful TCP connection is established, a performance entry of type net is generated. This entry contains information about the connection, including the time it took to establish the connection.

  4. Retrieving Entry Data: To access the performance data, we can use the getEntries() method on the PerformanceObserver. Each entry is an object with properties like duration (time taken) and name (event type).

Simplified Example:

"use strict";

const { PerformanceObserver } = require("perf_hooks");
const net = require("node:net");

const obs = new PerformanceObserver((items) => {
  items.getEntries().forEach((entry) => {
    console.log(`Connection took ${entry.duration}ms to establish.`);
  });
});

obs.observe({ entryTypes: ["net"] }); // Start observing network events

const PORT = 8080;
net
  .createServer((socket) => {
    socket.destroy(); // Close the socket immediately
  })
  .listen(PORT, () => {
    net.connect(PORT, () => {
      console.log("Connection established.");
    });
  });

Real-World Applications:

  • Monitoring TCP connection performance in web applications or APIs

  • Troubleshooting connection issues or slowdowns

  • Optimizing network performance in critical systems


Performance Measurement in Node.js

Measuring performance is crucial for optimizing code and improving user experience. Node.js provides various tools for measuring different aspects of performance, including the perf_hooks module.

Measuring DNS Resolution Time

The Domain Name System (DNS) translates human-readable domain names (like "example.com") into machine-readable IP addresses. Measuring DNS resolution time can help identify bottlenecks in network communication.

Using the PerformanceObserver

The PerformanceObserver allows you to observe and measure specific performance events. In this case, we're interested in the "dns" event, which is triggered when a DNS lookup is performed.

const { PerformanceObserver } = require("node:perf_hooks");
const dns = require("node:dns");

const obs = new PerformanceObserver((items) => {
  items.getEntries().forEach((item) => {
    console.log(item);
  });
});

obs.observe({ entryTypes: ["dns"] });
dns.lookup("localhost", () => {}); // Perform a DNS lookup

This code creates a PerformanceObserver that logs any DNS events. When you perform a DNS lookup using dns.lookup(), the event will be captured and printed to the console.

Interpreting the Results

The item object in the callback contains information about the DNS lookup, including:

  • name: The domain name being resolved

  • duration: The time it took to resolve the DNS in milliseconds

  • startTime: The time at which the DNS lookup started (relative to a specific time origin)

Applications in the Real World

Measuring DNS resolution time can be useful for:

  • Debugging network latency issues

  • Optimizing DNS caching strategies

  • Monitoring DNS performance over time

Measuring High-Resolution Time

Node.js also provides the process.hrtime() function for measuring high-resolution time with sub-millisecond precision. This can be useful for precisely measuring the duration of short-running events.

// Before the event
const start = process.hrtime();

// Event code here

// After the event
const end = process.hrtime(start);

const timeElapsed = end[1] - start[1]; // Time elapsed in nanoseconds
const timeElapsedMs = timeElapsed / 1000000; // Convert to milliseconds

Applications in the Real World

Measuring high-resolution time can be useful for:

  • Performance profiling of code

  • Benchmarking different algorithms or implementations

  • Profiling the execution time of specific sections of code