@mtharrison/pkg-profiler 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,91 +1,118 @@
1
1
  <p align="center">
2
- <svg xmlns="http://www.w3.org/2000/svg" width="120" height="120" viewBox="0 0 120 120" fill="none">
3
- <rect x="10" y="50" width="22" height="60" rx="4" fill="#6366f1" opacity="0.5"/>
4
- <rect x="38" y="30" width="22" height="80" rx="4" fill="#6366f1" opacity="0.7"/>
5
- <rect x="66" y="10" width="22" height="100" rx="4" fill="#6366f1" opacity="0.9"/>
6
- <circle cx="21" cy="40" r="6" fill="#f59e0b"/>
7
- <circle cx="49" cy="22" r="6" fill="#f59e0b"/>
8
- <circle cx="77" cy="6" r="6" fill="#f59e0b"/>
9
- <line x1="21" y1="40" x2="49" y2="22" stroke="#f59e0b" stroke-width="2"/>
10
- <line x1="49" y1="22" x2="77" y2="6" stroke="#f59e0b" stroke-width="2"/>
11
- <rect x="94" y="45" width="16" height="12" rx="2" fill="#6366f1"/>
12
- <rect x="94" y="61" width="16" height="12" rx="2" fill="#6366f1" opacity="0.7"/>
13
- <rect x="94" y="77" width="16" height="12" rx="2" fill="#6366f1" opacity="0.4"/>
14
- </svg>
2
+ <img src="assets/logo.svg" width="120" height="120" alt="where-you-at logo">
15
3
  </p>
16
4
 
17
5
  <h1 align="center">@mtharrison/pkg-profiler</h1>
18
6
 
19
7
  <p align="center">
20
- Zero-dependency sampling profiler that shows which npm packages consume your wall time.
8
+ <strong>Where's your wall time going? Find out in one call.</strong><br>
9
+ Zero-dependency sampling profiler that breaks down Node.js wall time by npm package.
21
10
  </p>
22
11
 
23
- ---
12
+ <p align="center">
13
+ <a href="https://www.npmjs.com/package/@mtharrison/pkg-profiler"><img src="https://img.shields.io/npm/v/@mtharrison/pkg-profiler" alt="npm version"></a>
14
+ <img src="https://img.shields.io/node/v/@mtharrison/pkg-profiler" alt="node version">
15
+ <a href="LICENSE"><img src="https://img.shields.io/npm/l/@mtharrison/pkg-profiler" alt="license"></a>
16
+ </p>
17
+
18
+ <p align="center">
19
+ <img src="assets/report-screenshot.png" width="660" alt="Example HTML report showing per-package wall time breakdown">
20
+ </p>
24
21
 
25
- ## The Problem
22
+ ## Quick Start
26
23
 
27
- You have a slow Node.js process -- maybe a test suite that takes too long, a server that's sluggish to start, or a CLI tool that lags. You fire up a profiler and get a wall of individual function timings. You can see *what* is slow, but not *where* the time is going at the package level.
24
+ ```typescript
25
+ import { start, stop } from '@mtharrison/pkg-profiler';
28
26
 
29
- What you really want to know is: **is the bottleneck in my code, or in a dependency?** And if it's a dependency, *which one*?
27
+ await start();
28
+ // ... your code here ...
29
+ const result = await stop();
30
+ result.writeHtml(); // writes an HTML report to cwd
31
+ ```
30
32
 
31
- `@mtharrison/pkg-profiler` gives you a per-package wall-time breakdown so you can instantly see whether you should be optimizing your own code or looking for a faster alternative to that one heavy dependency.
33
+ Or use the convenience wrapper:
32
34
 
33
- ## Installation
35
+ ```typescript
36
+ import { profile } from '@mtharrison/pkg-profiler';
34
37
 
35
- ```bash
36
- npm install @mtharrison/pkg-profiler
38
+ const result = await profile(async () => {
39
+ await build();
40
+ });
41
+ result.writeHtml();
37
42
  ```
38
43
 
39
- ## Usage
44
+ ## What You Get
40
45
 
41
- ```typescript
42
- import { track, report } from '@mtharrison/pkg-profiler';
46
+ A self-contained HTML report that shows exactly which npm packages are eating your wall time. The summary table gives you the top-level picture; expand the tree to drill into individual files and functions. First-party code is highlighted so you can instantly see whether the bottleneck is yours or a dependency's.
43
47
 
44
- await track();
48
+ ## API
45
49
 
46
- // ... your code here ...
50
+ ### `start(options?)`
47
51
 
48
- const reportPath = await report();
49
- console.log(`Report written to ${reportPath}`);
50
- ```
52
+ Start the V8 CPU sampling profiler. Safe no-op if already profiling.
51
53
 
52
- The generated HTML report shows a breakdown of wall time by package, with expandable trees to drill down into individual files and functions.
54
+ | Option | Type | Default | Description |
55
+ |------------|----------|---------|------------------------------------|
56
+ | `interval` | `number` | V8 default | Sampling interval in microseconds |
53
57
 
54
- ## API
58
+ ### `stop()`
59
+
60
+ Stop the profiler and return a `PkgProfile` containing the aggregated data. Resets the sample store afterward.
61
+
62
+ ### `clear()`
63
+
64
+ Stop profiling and discard all data without generating a profile.
55
65
 
56
- ### `track(options?)`
66
+ ### `profile(fn)`
57
67
 
58
- Starts the V8 CPU sampling profiler. If already profiling, this is a safe no-op.
68
+ Profile a block of code. Starts the profiler, runs `fn`, stops the profiler, and returns a `PkgProfile`.
59
69
 
60
- **Options:**
70
+ ```typescript
71
+ const result = await profile(async () => {
72
+ await runBuild();
73
+ await runTests();
74
+ });
75
+ const path = result.writeHtml();
76
+ ```
77
+
78
+ ### `profile({ onExit })`
61
79
 
62
- | Option | Type | Description |
63
- |------------|----------|------------------------------------------------|
64
- | `interval` | `number` | Sampling interval in microseconds (optional) |
80
+ Long-running mode for servers. Starts the profiler and registers shutdown handlers for SIGINT, SIGTERM, and `beforeExit`. When triggered, stops the profiler and calls `onExit` with the result.
65
81
 
66
- **Returns:** `Promise<void>`
82
+ ```typescript
83
+ await profile({ onExit: (result) => result.writeHtml() });
67
84
 
68
- ### `report()`
85
+ const app = createApp();
86
+ app.listen(3000);
87
+ // Ctrl+C → stop() called → onExit fires → writeHtml() → process exits
88
+ ```
69
89
 
70
- Stops the profiler, processes collected samples, generates an HTML report, and returns the absolute path to the report file. Resets all accumulated data after reporting (clean slate for the next cycle).
90
+ ### `PkgProfile`
71
91
 
72
- Returns an empty string if no samples were collected.
92
+ Returned by `stop()` and `profile()`. Contains aggregated profiling data.
73
93
 
74
- **Returns:** `Promise<string>` -- absolute path to the generated HTML report
94
+ | Property | Type | Description |
95
+ |---------------|------------------|------------------------------------------------|
96
+ | `timestamp` | `string` | When the profile was captured |
97
+ | `totalTimeUs` | `number` | Total sampled wall time in microseconds |
98
+ | `packages` | `PackageEntry[]` | Package breakdown sorted by time descending |
99
+ | `otherCount` | `number` | Number of packages below reporting threshold |
100
+ | `projectName` | `string` | Project name from package.json |
75
101
 
76
- ### `clear()`
102
+ #### `writeHtml(path?)`
77
103
 
78
- Stops the profiler (if running) and resets all accumulated sample data without generating a report.
104
+ Write a self-contained HTML report to disk. Returns the absolute path to the written file.
79
105
 
80
- **Returns:** `Promise<void>`
106
+ - **Default**: writes to `./where-you-at-{timestamp}.html` in the current directory
107
+ - **With path**: writes to the specified location
81
108
 
82
109
  ## How It Works
83
110
 
84
- The library uses the V8 CPU profiler (via `node:inspector`) to periodically sample the call stack. Each sample's leaf frame (the function currently executing) is attributed the elapsed wall time. File paths are resolved to npm packages by detecting `node_modules` segments, giving you a per-package time breakdown without any code instrumentation.
111
+ Uses the V8 CPU profiler (`node:inspector`) to sample the call stack at regular intervals. Each sample's leaf frame is attributed the elapsed wall time, then file paths are resolved to npm packages by walking up through `node_modules`. No code instrumentation required.
85
112
 
86
113
  ## Requirements
87
114
 
88
- - Node.js >= 20.0.0
115
+ Node.js >= 20.0.0
89
116
 
90
117
  ## License
91
118