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 🙏

© 2026 – Pkg Stats / Ryan Hefner

profiler-md

v0.8.1

Published

Converts performance profiles to human and LLM friendly Markdown.

Readme

[!NOTE]

This package is in beta and I'm excited for you to try it! Share suggestions, bug reports, and feature requests by filing an issue.

Demo

# CPU profile

Took 2.49s over 2,659 samples (939.9µs per sample).

| Category           |     % |    Time | Samples |
| ------------------ | ----: | ------: | ------: |
| Third-party        | 87.4% |   2.18s |   2,410 |
| Garbage collector  |  7.6% | 191.0ms |     156 |
| Standard library   |  3.9% |  96.8ms |      70 |
| Native             |  0.9% |  22.7ms |      20 |
| Regular expression |  0.1% |   2.5ms |       2 |
| Ours               |  0.1% |   1.3ms |       1 |

## Hottest functions

### Self time

Functions ranked by time spent directly in the function body, excluding callees.

|    % |    Time | Samples | Function                        | Location                                             |
| ---: | ------: | ------: | ------------------------------- | ---------------------------------------------------- |
| 7.6% | 191.0ms |     156 | `(garbage collector)`           | `<unknown>`                                          |
| 2.9% |  71.5ms |      57 | `wrapSafe`                      | `node:internal/modules/cjs/loader:1671:18`           |
| 2.8% |  69.0ms |      66 | `recursiveTypeRelatedTo`        | `node_modules/typescript/lib/typescript.js:64383:38` |
| 2.5% |  63.0ms |      66 | `isRelatedTo`                   | `node_modules/typescript/lib/typescript.js:63813:27` |
| 2.1% |  51.7ms |      43 | `checkTypeRelatedTo`            | `node_modules/typescript/lib/typescript.js:63505:32` |
…

The output continues with the hottest functions by total time, the hottest call stacks, and per-line, caller, and callee detail. See the full output, or examples/output/ for heap snapshots and diffs.

Features

  • Polyglot: profile, call graph, and heap snapshot formats across many languages
  • Profile analysis: sampling rates, category breakdowns, and the hottest functions, call stacks, lines, callers, and callees
  • Heap analysis: self and dominator-based retained sizes, retainer paths, and the largest constructors and strings
  • Multi-profile inputs: one all JFR recording becomes CPU, allocation, and lock contention profiles
  • Diffing: ranked regressions and improvements between two profiles or two heap snapshots, across formats and profilers
  • Source maps: resolves minified and transpiled locations back to original sources
  • Zero config: auto-detects the format and profiler
  • Configurable: top entry counts, base URLs, categorization, filtering, and diff matching
  • CLI and API: a command line and a fully-typed API with sync and async variants (API docs)
  • Self-documenting: --help <language> and --help <format> explain how to generate and read each profile type
  • Agent-ready: ships a skill that guides an agent through profiling and optimizing your code

Install

# npm
$ npm i -g profiler-md

# Homebrew
$ brew install tomeraberbach/tap/profiler-md
# Bash (Linux)
$ profiler-md --completion bash > ~/.local/share/bash-completion/completions/profiler-md

# Bash (macOS/Homebrew)
$ profiler-md --completion bash > $(brew --prefix)/etc/bash_completion.d/profiler-md

# Fish
$ profiler-md --completion fish > ~/.config/fish/completions/profiler-md.fish

# Zsh
$ profiler-md --completion zsh > ~/.zfunc/_profiler-md

# PowerShell
$ profiler-md --completion pwsh >> $PROFILE.CurrentUserCurrentHost

Usage

CLI

# Convert a profile, paged and syntax highlighted
$ profiler-md profile.cpuprofile

# Diff two profiles or two heap snapshots
$ profiler-md base.cpuprofile current.cpuprofile

# Write the Markdown to a file
$ profiler-md profile.pb.gz -o profile.md

# Read a profile from stdin
$ node --cpu-prof app.js && cat *.cpuprofile | profiler-md
$ profiler-md --help
Usage: profiler-md [(-h/--help [TOPIC])] [-f/--format FORMAT] [-r/--origin
       ORIGIN] [-o/--output FILE] [--top-n N] [--min-category-share FRACTION] [
       --base-url STRING] [--source-maps GLOB...] [--match-name
       REGEX=REPLACEMENT...] [--match-location REGEX=REPLACEMENT...] [--category
       REGEX=CATEGORY...] [--hide REGEX...] [--show REGEX...] [--hide-category
       CATEGORY...] [--show-category CATEGORY...] [--no-pager] [--color/
       --no-color] ([FILE] | BASE CURRENT)

Converts performance profiles to human and LLM friendly Markdown.

  -h, --help [TOPIC]                  Show this help message or topic docs
  -f, --format FORMAT                 Input profile format (default: auto)
  -r, --origin ORIGIN                 Input profile origin (default: auto)
  -o, --output FILE                   Output file (default: - for stdout)
  --top-n N                           Entries to show per ranking, including 
                                      category subsections (default: 20)
  --min-category-share FRACTION       Share of a profile a category needs for 
                                      its own subsection, from 0 to 1 (default: 
                                      0.01)
  --base-url STRING                   Base URL or path to show paths relative 
                                      to, or "auto" for their common ancestor 
                                      (default: cwd)
  --source-maps GLOB                  Source maps (JSON or inline) to apply to 
                                      locations (repeatable)
  --match-name REGEX=REPLACEMENT      Rewrite names matching REGEX to 
                                      REPLACEMENT when pairing diffed entries 
                                      (repeatable)
  --match-location REGEX=REPLACEMENT  Rewrite locations (URL, path, or logical 
                                      name) matching REGEX to REPLACEMENT when 
                                      pairing diffed entries (repeatable)
  --category REGEX=CATEGORY           Categorize functions whose name or 
                                      location matches REGEX as CATEGORY, first 
                                      rule winning (repeatable)
  --hide REGEX                        Hide entries whose name or location 
                                      matches REGEX, still counting hidden 
                                      entries in totals (repeatable)
  --show REGEX                        Show only entries whose name or location 
                                      matches REGEX, still counting hidden 
                                      entries in totals (repeatable)
  --hide-category CATEGORY            Hide entries of CATEGORY, still counting 
                                      hidden entries in totals (repeatable)
  --show-category CATEGORY            Show only entries of CATEGORY, still 
                                      counting hidden entries in totals 
                                      (repeatable)
  --no-pager                          Disable stdout paging (default: auto)
  --color, --no-color                 Enable or disable ANSI syntax 
                                      highlighting (default: auto)
  FILE                                Profile to convert (default: stdin)
  BASE                                Base profile to diff
  CURRENT                             Current profile to diff against the base

Formats: callgrind, collapsed, ghc-eventlog, ghc-json-profile, hprof, jfr, jsc-heap-snapshot, memray, perf, pprof, speedscope, systing, v8-cpu-profile, v8-heap-profile, v8-heap-snapshot, webkit-timeline-recording
Origins: async-profiler, bun, chrome, deno, dotnet-trace, eflambe, excimer, ghc, go, gperftools, jdk, memray, node, node-pprof, perf, pprof-jl, pprof-rs, profile-jl, py-spy, pyinstrument, rbspy, safari, simpleperf, systing, tachyon, unknown, valgrind
Function categories: ours, third-party, stdlib, native, unknown, garbage-collector, compiler, jit, regexp, kernel, idle
Heap snapshot categories: object, array, string, concatenated-string, sliced-string, function, code, regexp, number, big-number, symbol, native, object-shape, internal, synthetic, unknown
Languages: c/cpp, csharp/fsharp, elixir/erlang, fortran, go, haskell, java/kotlin/groovy, javascript/typescript, julia, php, python, ruby, rust, swift, zig

API

import { openAsBlob } from 'node:fs'
import { diffProfilesAsync, profileToMdAsync } from 'profiler-md'

// Convert a profile or heap snapshot. The format and origin are auto-detected
console.log(await profileToMdAsync(await openAsBlob(`example.cpuprofile`)))

// Diff two profiles or two heap snapshots
console.log(
  await diffProfilesAsync(
    await openAsBlob(`base.cpuprofile`),
    await openAsBlob(`current.cpuprofile`),
  ),
)

See the API docs for sync variants, explicit formats and origins, and configuration callbacks.

Skill

Use the profiler-md skill to have an agent profile and optimize your code:

$ npx skills add TomerAberbach/profiler-md --skill profile-optimize

See skills.sh for more info.

Fun fact: the skill has profiled and optimized profiler-md itself!

Languages and formats

The table lists only the formats each language's own tools generate. Third-party tools convert others. Each format's docs explain how to generate and read it.

Contributing

Stars are always welcome!

For bugs and feature requests, create an issue.

License

MIT © Tomer Aberbach