wukong-profiler 1.0.3 → 1.0.4

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,5 +1,23 @@
1
1
  # wukong-profiler
2
2
 
3
+ <p align="center">
4
+ <a href="https://www.npmjs.com/package/wukong-profiler">
5
+ <img src="https://img.shields.io/npm/v/wukong-profiler.svg" alt="npm version">
6
+ </a>
7
+ <a href="https://www.npmjs.com/package/wukong-profiler">
8
+ <img src="https://img.shields.io/npm/dm/wukong-profiler.svg" alt="downloads">
9
+ </a>
10
+ <a href="https://github.com/tomatobybike/wukong-profiler/blob/master/LICENSE">
11
+ <img src="https://img.shields.io/github/license/tomatobybike/wukong-profiler.svg" alt="license">
12
+ </a>
13
+ <a href="https://github.com/tomatobybike/wukong-profiler">
14
+ <img src="https://img.shields.io/github/stars/tomatobybike/wukong-profiler.svg?style=social" alt="GitHub stars">
15
+ </a>
16
+ <a href="https://github.com/tomatobybike/wukong-profiler/issues">
17
+ <img src="https://img.shields.io/github/issues/tomatobybike/wukong-profiler.svg" alt="issues">
18
+ </a>
19
+ </p>
20
+
3
21
  🔥 High-performance Node/CLI profiler supporting:
4
22
 
5
23
  - Nested steps (true Flame Graph)
@@ -216,7 +234,7 @@ console.log('Total time:', total, 'ms')
216
234
  - Chrome Trace export compatible with Chrome's `chrome://tracing`
217
235
  - Profile diff for performance regression detection
218
236
 
219
- ## 🔍 Keywords
237
+
220
238
 
221
239
  <!--
222
240
  Node.js profiler, JavaScript profiler, Node performance analysis, CLI profiler,
package/README.zh-CN.md CHANGED
@@ -231,8 +231,6 @@ console.log('总耗时:', total, 'ms')
231
231
 
232
232
  ---
233
233
 
234
- ## 🔍 关键词
235
-
236
234
  <!--
237
235
  Node.js profiler, JavaScript profiler, Node performance analysis, CLI profiler,
238
236
  Flame Graph, Flame Chart, Chrome Trace, Chrome tracing, Perfetto,
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wukong-profiler",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "🔥 高性能 CLI/Node Profiler,支持 Flame Graph、Chrome Trace、HOT 步骤检测、性能回归分析",
5
5
  "keywords": [
6
6
  "profiler",
@@ -1,56 +1,56 @@
1
- // testFunction.mjs
2
- import { measure, createProfiler } from 'wukong-profiler'
3
- import fs from 'fs'
4
-
5
- // 创建 Profiler,可全局配置
6
- const profiler = createProfiler({
7
- enabled: true,
8
- verbose: true,
9
- flame: true,
10
- trace: 'trace.json',
11
- hotThreshold: 0.8,
12
- failOnHot: true
13
- })
14
-
15
- // 被测试函数
16
- function heavyComputation(n) {
17
- let sum = 0
18
- for (let i = 0; i < n * 1e6; i++) sum += i
19
- return sum
20
- }
21
-
22
- function nestedComputation(n) {
23
- return measure('nestedComputation', () => {
24
- const a = measure('heavyComputation', () => heavyComputation(n))
25
- const b = measure('heavyComputation_half', () => heavyComputation(n / 2))
26
- return a + b
27
- })
28
- }
29
-
30
- // === 测试入口 ===
31
- measure('Test: heavyComputation', () => heavyComputation(5))
32
- measure('Test: nestedComputation', () => nestedComputation(3))
33
-
34
- // 完成并输出总耗时
35
- const result = profiler.end('Total Test')
36
-
37
- // 输出 Chrome Trace
38
- if (profiler.traceFile) {
39
- const traceEvents = result.events.map(ev => ({
40
- name: ev.name,
41
- ph: 'X',
42
- ts: Math.round(ev.sinceStart * 1000), // μs
43
- dur: Math.round(ev.duration * 1000), // μs
44
- pid: 1,
45
- tid: 1
46
- }))
47
- fs.writeFileSync(profiler.traceFile, JSON.stringify({ traceEvents }, null, 2))
48
- console.log(`Chrome Trace 已生成: ${profiler.traceFile}`)
49
- }
50
-
51
- // HOT 步骤触发 CI 非零退出码
52
- const anyHot = result.events.some(ev => ev.hot)
53
- if (anyHot && profiler.failOnHot) {
54
- console.error('🔥 HOT step detected! Exiting with code 1.')
55
- process.exit(1)
56
- }
1
+ // testFunction.mjs
2
+ import { measure, createProfiler } from 'wukong-profiler'
3
+ import fs from 'fs'
4
+
5
+ // 创建 Profiler,可全局配置
6
+ const profiler = createProfiler({
7
+ enabled: true,
8
+ verbose: true,
9
+ flame: true,
10
+ trace: 'trace.json',
11
+ hotThreshold: 0.8,
12
+ failOnHot: true
13
+ })
14
+
15
+ // 被测试函数
16
+ function heavyComputation(n) {
17
+ let sum = 0
18
+ for (let i = 0; i < n * 1e6; i++) sum += i
19
+ return sum
20
+ }
21
+
22
+ function nestedComputation(n) {
23
+ return measure('nestedComputation', () => {
24
+ const a = measure('heavyComputation', () => heavyComputation(n))
25
+ const b = measure('heavyComputation_half', () => heavyComputation(n / 2))
26
+ return a + b
27
+ })
28
+ }
29
+
30
+ // === 测试入口 ===
31
+ measure('Test: heavyComputation', () => heavyComputation(5))
32
+ measure('Test: nestedComputation', () => nestedComputation(3))
33
+
34
+ // 完成并输出总耗时
35
+ const result = profiler.end('Total Test')
36
+
37
+ // 输出 Chrome Trace
38
+ if (profiler.traceFile) {
39
+ const traceEvents = result.events.map(ev => ({
40
+ name: ev.name,
41
+ ph: 'X',
42
+ ts: Math.round(ev.sinceStart * 1000), // μs
43
+ dur: Math.round(ev.duration * 1000), // μs
44
+ pid: 1,
45
+ tid: 1
46
+ }))
47
+ fs.writeFileSync(profiler.traceFile, JSON.stringify({ traceEvents }, null, 2))
48
+ console.log(`Chrome Trace 已生成: ${profiler.traceFile}`)
49
+ }
50
+
51
+ // HOT 步骤触发 CI 非零退出码
52
+ const anyHot = result.events.some(ev => ev.hot)
53
+ if (anyHot && profiler.failOnHot) {
54
+ console.error('🔥 HOT step detected! Exiting with code 1.')
55
+ process.exit(1)
56
+ }
package/src/index.mjs CHANGED
@@ -1,12 +1,12 @@
1
- import { createProfiler } from './utils/profiler.mjs'
2
- import { formatTime, makeBar } from './utils/format.mjs'
3
- import { exportChromeTrace } from './utils/trace.mjs'
4
- import { diffProfiles } from './utils/diff.mjs'
5
-
6
- export {
7
- createProfiler,
8
- formatTime,
9
- makeBar,
10
- exportChromeTrace,
11
- diffProfiles
12
- }
1
+ import { createProfiler } from './utils/profiler.mjs'
2
+ import { formatTime, makeBar } from './utils/format.mjs'
3
+ import { exportChromeTrace } from './utils/trace.mjs'
4
+ import { diffProfiles } from './utils/diff.mjs'
5
+
6
+ export {
7
+ createProfiler,
8
+ formatTime,
9
+ makeBar,
10
+ exportChromeTrace,
11
+ diffProfiles
12
+ }
@@ -1,21 +1,21 @@
1
- export const diffProfiles = (prev, curr, threshold = 0.2) => {
2
- const map = new Map()
3
- prev.events.forEach(e => map.set(e.name, e.duration))
4
- const regressions = []
5
-
6
- curr.events.forEach(e => {
7
- const before = map.get(e.name)
8
- if (!before) return
9
- const diff = (e.duration - before) / before
10
- if (diff >= threshold) {
11
- regressions.push({
12
- name: e.name,
13
- before,
14
- after: e.duration,
15
- diff
16
- })
17
- }
18
- })
19
-
20
- return regressions
21
- }
1
+ export const diffProfiles = (prev, curr, threshold = 0.2) => {
2
+ const map = new Map()
3
+ prev.events.forEach(e => map.set(e.name, e.duration))
4
+ const regressions = []
5
+
6
+ curr.events.forEach(e => {
7
+ const before = map.get(e.name)
8
+ if (!before) return
9
+ const diff = (e.duration - before) / before
10
+ if (diff >= threshold) {
11
+ regressions.push({
12
+ name: e.name,
13
+ before,
14
+ after: e.duration,
15
+ diff
16
+ })
17
+ }
18
+ })
19
+
20
+ return regressions
21
+ }
@@ -1,11 +1,11 @@
1
- export const formatTime = (ms) => {
2
- if (ms < 1) return `${(ms * 1000).toFixed(2)} μs`
3
- if (ms < 1000) return `${ms.toFixed(2)} ms`
4
- if (ms < 60000) return `${(ms / 1000).toFixed(2)} s`
5
- return `${(ms / 60000).toFixed(2)} min`
6
- }
7
-
8
- export const makeBar = (ratio, width = 32) => {
9
- const len = Math.max(1, Math.round(ratio * width))
10
- return '█'.repeat(len)
11
- }
1
+ export const formatTime = (ms) => {
2
+ if (ms < 1) return `${(ms * 1000).toFixed(2)} μs`
3
+ if (ms < 1000) return `${ms.toFixed(2)} ms`
4
+ if (ms < 60000) return `${(ms / 1000).toFixed(2)} s`
5
+ return `${(ms / 60000).toFixed(2)} min`
6
+ }
7
+
8
+ export const makeBar = (ratio, width = 32) => {
9
+ const len = Math.max(1, Math.round(ratio * width))
10
+ return '█'.repeat(len)
11
+ }