npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

perf-agent

v0.4.0

Published

An agent designed to give insight into the performance of your node.js code.

Downloads

7

Readme

Perf Agent

An agent designed to give insight into the performance of your node.js code.

Perf Agent uses async_hooks to observe the duration of each synchronous block of code. To gain further insight, Perf Agent allows for the collection of deep asynchronous stack traces.

When asynchronous stack traces are enabled, it is also possible to use the agent as an alternative to Error.captureStackTrace in order to see the full, asynchronous call stack leading up to an event.

Example

const agent = new PerfAgent({
    captureAsyncStackTraces: true,
    threshold: 100, // Trigger events if a block exceeds 100ms
});

agent.onBlocked(e => {
    // e.duration will be the number of nanoseconds elapsed in a synchronous block
    // e.stacks is an array of arrays of Frame objects
    // e.stacks[0][0] is the Frame that *triggered* the block that exceeded the threshold
    console.log(e.toString()); // Log the event which will include a deep stack trace
});
agent.start(); // The agent must be explicitly started

Here's what a deep stack trace might look like (from the tests). The lines beginning with an arrow represent distinct asynchronous contexts. Below you can see that two Promise resolution handlers were invoked on the same line and that the 2nd blocked for 101ms.

Slow synchronous block (101ms):
--> Promise.then (<anonymous>)
    it (/Users/ggoodman/Projects/experiments/perf-agent/test/stack_traces.js:46:52)
    Immediate.setImmediate [as _onImmediate] (/Users/ggoodman/Projects/experiments/perf-agent/node_modules/lab/lib/runner.js:597:31)
    runCallback (timers.js:810:20)
    tryOnImmediate (timers.js:768:5)
    processImmediate [as _immediateCallback] (timers.js:745:5)
--> Promise.then (<anonymous>)
    it (/Users/ggoodman/Projects/experiments/perf-agent/test/stack_traces.js:46:32)
    Immediate.setImmediate [as _onImmediate] (/Users/ggoodman/Projects/experiments/perf-agent/node_modules/lab/lib/runner.js:597:31)
    runCallback (timers.js:810:20)
    tryOnImmediate (timers.js:768:5)
    processImmediate [as _immediateCallback] (timers.js:745:5)

API

PerfAgent

const { PerfAgent } = require('perf-agent');

An instance of the perf agent.

new PerfAgent(options): create a new PerfAgent instance where options must be an object having:

  • captureAsyncStackTraces?: boolean whether asynchronous stack traces should be collected. There can be a major performance impact in collecting these.
  • threshold: number the threshold in milliseconds above which BlockedEvents will be triggered

.start(): start capturing async stack traces (if enabled) and observing for slow synchronous blocks.

.stop(): stop capturing async stack traces (if enabled) and observing for slow synchronous blocks.

.captureStackTrace(receiver, callsite): capture a stack trace (which may be augmented with asynchronous frames, if enabled), similar to Error.captureStackTrace.

.executeWithoutTracing(cb): execute the provided callback function such that it (and it's continuations) will not be traced.

.onBlocked(cb): register a callback that will be invoked when a synchronous block exceeds the configured threshold where:

  • cb: (event: BlockedEvent): void

Returns a Disposable whose .dispose() method can be invoked to unregister the callback.

.setUseAsyncStackTraces(enabled): toggle the collection of async stack traces where:

  • enabled: boolean whether async stack traces should be collected.

Note: when enabled, any pre-existing asynchronous contexts will have empty stacks. In other words, retroactive collection is not possible.

BlockedEvent

BlockedEvent represents the data collected about a slow synchronous block.

.duration: number: The number of nanoseconds elapsed while executing the block.

.stacks: Frame[][]: An array of stack traces where each element in the top-level array represents a synchronous block's stack trace.

Stacks and their elements are ordered such that the newest events are first.

You can think of each element in the top-level array as being a logical consequence of the previous element.

.toString(): Generate a string representation of the event.

Frame

Frame represents a function invocation in a stack trace. It is a simplified version of a NodeJS.CallSite object whose objective is to reduce the memory pressure associated with collecting many such objects.

.columnNumber: number

.fileName: string

.functionName: string

.isConstructor: readonly boolean

.isEval: readonly boolean

.isNative: readonly boolean

.isToplevel: readonly boolean

.lineNumber: number

.methodName: string

.typeName: string