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

ep_performance_test_hooks

v0.0.61

Published

Etherpad plugin to show performance stats in /stats url

Readme

Publish Status Backend Tests Status

Performance Test Hooks for Etherpad

See exactly how long your Etherpad takes to become editable — and which assets weigh it down — straight from the browser, with no external APM.

This plugin instruments the client lifecycle: it times every Etherpad boot hook (documentReadypostAceInit) and records the load time and byte size of every resource the pad, outer frame, and inner editor request. The data is exposed as JSON at /stats, ready to graph, alert on, or diff between releases.

Why you'd want it

  • Find the slow phase of pad load. The boot waterfall (etherpadHooksDuration) shows the cost of each lifecycle stage, so you know whether time goes to the editor, the toolbar, or plugin init — not just a single opaque "load time".
  • Catch asset bloat before users do. Per-resource decoded/encoded/transfer sizes make it obvious when a font, locale bundle, or plugin asset balloons.
  • Spot regressions across releases. /stats is plain JSON, so you can snapshot it in CI and fail the build when boot time or payload size creeps up.
  • No third-party APM. Everything is collected with the browser's own PerformanceResourceTiming API and stays on your server.

The data

Open any pad (this is what populates the metrics), then GET /stats. The plugin's output lives under the ep_performance_test_hooks key. Below is a real response from an Etherpad running this plugin — the values are exactly as captured; only explanatory // comments have been added and the loadTimes/loadSizes maps truncated (the full response carries every resource across all three frames — 49 + 49 + 46 in this capture):

{
  "ep_performance_test_hooks": {
    // Wall-clock timestamp each lifecycle hook fired
    "etherpadHooks": {
      "documentReady": 1781864859040,
      "aceInitInnerdocbodyHead": 1781864859200,
      "aceInitialized": 1781864859220,
      "postToolbarInit": 1781864859250,
      "postAceInit": 1781864859323
    },
    // The boot waterfall: ms from documentReady to each hook
    "etherpadHooksDuration": {
      "documentReady": 0,
      "aceInitInnerdocbodyHead": 160,
      "aceInitialized": 180,
      "postToolbarInit": 210,
      "postAceInit": 283          // editor interactive 283 ms after documentReady
    },
    // Per-resource timing for the main / outer / inner frames (2 of 49 shown)
    "loadTimes": {
      "main": {
        "/static/css/pad.css": {
          "redirectTime": 0, "domainLookupTime": 0, "tcpTime": 0,
          "secureConnectionTime": "0", "responseTime": 0,
          "fetchUntilResponseEndTime": 0,
          "requestStartUntilResponseEndTime": 0,
          "startUntilResponseEndTime": 0
        }
      }
    },
    // Per-resource byte sizes (2 of 49 shown)
    "loadSizes": {
      "main": {
        "/static/css/pad.css":               { "decodedBodySize": 9279, "encodedBodySize": 9279, "transferSize": 0 },
        "/static/skins/colibris/pad.css":    { "decodedBodySize": 2145, "encodedBodySize": 2145, "transferSize": 0 }
      }
    }
  }
}

What's measured

| Field | What it tells you | | --- | --- | | etherpadHooks | Wall-clock timestamp each lifecycle hook fired | | etherpadHooksDuration | Milliseconds from documentReady to each hook — the boot waterfall | | loadTimes.{main,outer,inner} | Redirect / DNS / TCP / TLS / response timings per resource, for each of the three pad frames | | loadSizes.{main,outer,inner} | decodedBodySize / encodedBodySize / transferSize per resource | | performance | The page's navigation PerformanceEntry |

Usage

The plugin only emits data — render or alert on it however you like. For example, fail CI if the editor takes too long to become interactive:

curl -s http://localhost:9001/stats \
  | jq '.ep_performance_test_hooks.etherpadHooksDuration.postAceInit'   # -> 283

…or find your heaviest assets:

curl -s http://localhost:9001/stats \
  | jq -r '.ep_performance_test_hooks.loadSizes.main
           | to_entries | sort_by(-.value.decodedBodySize)[:10][]
           | "\(.value.decodedBodySize)\t\(.key)"'

Installation

Install from the Etherpad admin UI (Admin → Manage Plugins, search for ep_performance_test_hooks and click Install), or from the Etherpad root directory:

pnpm run plugins install ep_performance_test_hooks

⚠️ Don't run npm i / npm install yourself from the Etherpad source tree — Etherpad tracks installed plugins through its own plugin-manager, and hand-editing package.json can leave the server unable to start.

After installing, restart Etherpad.