@kylincloud/flamegraph 0.35.28 → 0.36.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/FlameGraph/FlameGraphComponent/Flamegraph.d.ts +16 -2
  3. package/dist/FlameGraph/FlameGraphComponent/Flamegraph.d.ts.map +1 -1
  4. package/dist/FlameGraph/FlameGraphComponent/Flamegraph_render.d.ts +15 -2
  5. package/dist/FlameGraph/FlameGraphComponent/Flamegraph_render.d.ts.map +1 -1
  6. package/dist/FlameGraph/FlameGraphComponent/Highlight.d.ts.map +1 -1
  7. package/dist/FlameGraph/FlameGraphComponent/index.d.ts.map +1 -1
  8. package/dist/FlameGraph/normalize.d.ts.map +1 -1
  9. package/dist/FlameGraph/uniqueness.d.ts.map +1 -1
  10. package/dist/ProfilerTable.d.ts.map +1 -1
  11. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  12. package/dist/flamegraphRenderWorker.js +2 -0
  13. package/dist/flamegraphRenderWorker.js.map +1 -0
  14. package/dist/index.cjs.js +4 -4
  15. package/dist/index.cjs.js.map +1 -1
  16. package/dist/index.esm.js +4 -4
  17. package/dist/index.esm.js.map +1 -1
  18. package/dist/index.node.cjs.js +4 -4
  19. package/dist/index.node.cjs.js.map +1 -1
  20. package/dist/index.node.esm.js +4 -4
  21. package/dist/index.node.esm.js.map +1 -1
  22. package/dist/shims/Table.d.ts +15 -1
  23. package/dist/shims/Table.d.ts.map +1 -1
  24. package/dist/workers/createFlamegraphRenderWorker.d.ts +2 -0
  25. package/dist/workers/createFlamegraphRenderWorker.d.ts.map +1 -0
  26. package/dist/workers/flamegraphRenderWorker.d.ts +2 -0
  27. package/dist/workers/flamegraphRenderWorker.d.ts.map +1 -0
  28. package/dist/workers/profilerTableWorker.d.ts +73 -0
  29. package/dist/workers/profilerTableWorker.d.ts.map +1 -0
  30. package/package.json +1 -1
  31. package/src/FlameGraph/FlameGraphComponent/Flamegraph.ts +33 -8
  32. package/src/FlameGraph/FlameGraphComponent/Flamegraph_render.ts +289 -85
  33. package/src/FlameGraph/FlameGraphComponent/Highlight.tsx +43 -17
  34. package/src/FlameGraph/FlameGraphComponent/index.tsx +119 -1
  35. package/src/FlameGraph/normalize.ts +9 -7
  36. package/src/FlameGraph/uniqueness.ts +69 -59
  37. package/src/ProfilerTable.tsx +421 -33
  38. package/src/Tooltip/Tooltip.tsx +49 -16
  39. package/src/shims/Table.module.scss +5 -0
  40. package/src/shims/Table.tsx +195 -5
  41. package/src/workers/createFlamegraphRenderWorker.ts +23 -0
  42. package/src/workers/flamegraphRenderWorker.ts +192 -0
  43. package/src/workers/profilerTableWorker.ts +342 -0
@@ -29,6 +29,15 @@ export type TableBodyType = {
29
29
  } | {
30
30
  type: 'filled';
31
31
  bodyRows: BodyRow[];
32
+ } | {
33
+ type: 'virtual';
34
+ rowCount: number;
35
+ rows: BodyRow[];
36
+ range: {
37
+ start: number;
38
+ end: number;
39
+ };
40
+ onRangeChange?: (start: number, end: number) => void;
32
41
  };
33
42
  type Table = TableBodyType & {
34
43
  headRow: HeadCell[];
@@ -48,7 +57,12 @@ interface TableProps {
48
57
  className?: string;
49
58
  isLoading?: boolean;
50
59
  itemsPerPage?: number;
60
+ virtualize?: boolean;
61
+ virtualizeRowHeight?: number;
62
+ virtualizeOverscan?: number;
63
+ scrollRef?: RefObject<HTMLElement>;
64
+ disableSort?: boolean;
51
65
  }
52
- declare function Table({ sortByDirection, sortBy, updateSortParams, table, tableBodyRef, className, isLoading, itemsPerPage, }: TableProps): import("react/jsx-runtime").JSX.Element;
66
+ declare function Table({ sortByDirection, sortBy, updateSortParams, table, tableBodyRef, className, isLoading, itemsPerPage, virtualize, virtualizeRowHeight, virtualizeOverscan, scrollRef, disableSort, }: TableProps): import("react/jsx-runtime").JSX.Element;
53
67
  export default Table;
54
68
  //# sourceMappingURL=Table.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../src/shims/Table.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAoB,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAUrF,UAAU,UAAU;IAClB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;CACvH;AAED,MAAM,WAAW,IAAK,SAAQ,UAAU;IACtC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,UAAU,QAAS,SAAQ,UAAU;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,OAAO;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,aAAa,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,aAAa,GACrB;IACA,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GACC;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB,CAAC;AAEJ,KAAK,KAAK,GAAG,aAAa,GAAG;IAC3B,OAAO,EAAE,QAAQ,EAAE,CAAC;CACrB,CAAC;AAEF,UAAU,cAAc;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,eAAe,EAAE,MAAM,GAAG,KAAK,CAAC;CACjC;AAED,eAAO,MAAM,YAAY,YAAa,QAAQ,EAAE,KAAG,cAsBlD,CAAC;AAEF,UAAU,UAAU;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,KAAK,EAAE,KAAK,CAAC;IACb,YAAY,CAAC,EAAE,SAAS,CAAC,uBAAuB,CAAC,CAAC;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA0CD,iBAAS,KAAK,CAAC,EACb,eAAe,EACf,MAAM,EACN,gBAAgB,EAChB,KAAK,EACL,YAAY,EACZ,SAAS,EACT,SAAS,EACT,YAAY,GACb,EAAE,UAAU,2CAuEZ;AA2DD,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"Table.d.ts","sourceRoot":"","sources":["../../src/shims/Table.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function createFlamegraphRenderWorker(): Worker;
2
+ //# sourceMappingURL=createFlamegraphRenderWorker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createFlamegraphRenderWorker.d.ts","sourceRoot":"","sources":["../../src/workers/createFlamegraphRenderWorker.ts"],"names":[],"mappings":"AAAA,wBAAgB,4BAA4B,IAAI,MAAM,CAsBrD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=flamegraphRenderWorker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flamegraphRenderWorker.d.ts","sourceRoot":"","sources":["../../src/workers/flamegraphRenderWorker.ts"],"names":[],"mappings":""}
@@ -0,0 +1,73 @@
1
+ export type ProfilerTableWorkerRow = {
2
+ type: 'single';
3
+ name: string;
4
+ self: number;
5
+ total: number;
6
+ } | {
7
+ type: 'double';
8
+ name: string;
9
+ totalLeft: number;
10
+ totalRght: number;
11
+ leftTicks: number;
12
+ rightTicks: number;
13
+ };
14
+ export type ProfilerTableWorkerRequest = {
15
+ type: 'init';
16
+ payload: {
17
+ flamebearer: {
18
+ names: string[];
19
+ levels: number[][];
20
+ format: 'single' | 'double';
21
+ leftTicks?: number;
22
+ rightTicks?: number;
23
+ };
24
+ sortBy: string;
25
+ sortByDirection: 'asc' | 'desc';
26
+ highlightQuery: string;
27
+ };
28
+ } | {
29
+ type: 'update';
30
+ payload: {
31
+ sortBy: string;
32
+ sortByDirection: 'asc' | 'desc';
33
+ highlightQuery: string;
34
+ };
35
+ } | {
36
+ type: 'range';
37
+ payload: {
38
+ start: number;
39
+ end: number;
40
+ requestId: number;
41
+ };
42
+ } | {
43
+ type: 'findNode';
44
+ payload: {
45
+ name: string;
46
+ requestId: number;
47
+ };
48
+ };
49
+ export type ProfilerTableWorkerResponse = {
50
+ type: 'ready';
51
+ payload: {
52
+ rowCount: number;
53
+ };
54
+ } | {
55
+ type: 'range';
56
+ payload: {
57
+ rows: ProfilerTableWorkerRow[];
58
+ start: number;
59
+ end: number;
60
+ requestId: number;
61
+ };
62
+ } | {
63
+ type: 'findNode';
64
+ payload: {
65
+ node: {
66
+ i: number;
67
+ j: number;
68
+ } | null;
69
+ requestId: number;
70
+ };
71
+ };
72
+ export declare function createProfilerTableWorker(): Worker;
73
+ //# sourceMappingURL=profilerTableWorker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profilerTableWorker.d.ts","sourceRoot":"","sources":["../../src/workers/profilerTableWorker.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAC9B;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,GACD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEN,MAAM,MAAM,0BAA0B,GAClC;IACE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QACP,WAAW,EAAE;YACX,KAAK,EAAE,MAAM,EAAE,CAAC;YAChB,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;YACnB,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;YAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,UAAU,CAAC,EAAE,MAAM,CAAC;SACrB,CAAC;QACF,MAAM,EAAE,MAAM,CAAC;QACf,eAAe,EAAE,KAAK,GAAG,MAAM,CAAC;QAChC,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH,GACD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE;QACP,MAAM,EAAE,MAAM,CAAC;QACf,eAAe,EAAE,KAAK,GAAG,MAAM,CAAC;QAChC,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,GACD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAEN,MAAM,MAAM,2BAA2B,GACnC;IACE,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE;QACP,IAAI,EAAE,sBAAsB,EAAE,CAAC;QAC/B,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,GACD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE;QACP,IAAI,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAC;QACtC,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAEN,wBAAgB,yBAAyB,IAAI,MAAM,CAqQlD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kylincloud/flamegraph",
3
- "version": "0.35.28",
3
+ "version": "0.36.0",
4
4
  "description": "KylinCloud flamegraph renderer (Pyroscope-based)",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.node.cjs.js",
@@ -28,7 +28,7 @@ export default class Flamegraph {
28
28
 
29
29
  constructor(
30
30
  private readonly flamebearer: Flamebearer,
31
- private canvas: HTMLCanvasElement,
31
+ private canvas: HTMLCanvasElement | OffscreenCanvas,
32
32
  /**
33
33
  * What node to be 'focused'
34
34
  * ie what node to start the tree
@@ -75,11 +75,26 @@ export default class Flamegraph {
75
75
  }
76
76
  }
77
77
 
78
- public render(options?: { renderRects?: boolean; renderText?: boolean }) {
78
+ public render(options?: {
79
+ renderRects?: boolean;
80
+ renderText?: boolean;
81
+ highlightQueryOverride?: string;
82
+ renderMode?: 'normal' | 'highlightOnly' | 'forceGrey';
83
+ levelStart?: number;
84
+ levelEnd?: number;
85
+ startI?: number;
86
+ startJ?: number;
87
+ timeBudgetMs?: number;
88
+ skipCanvasResize?: boolean;
89
+ skipDprScale?: boolean;
90
+ devicePixelRatio?: number;
91
+ }): { done: boolean; nextI: number; nextJ: number } {
79
92
  const { rangeMin, rangeMax, pxPerTick } = this.updateCachedMetrics();
80
93
  const tickToX = (i: number) => {
81
94
  return (i - this.flamebearer.numTicks * rangeMin) * pxPerTick;
82
95
  };
96
+ const highlightQuery =
97
+ options?.highlightQueryOverride ?? this.highlightQuery;
83
98
 
84
99
  const props = {
85
100
  canvas: this.canvas,
@@ -99,7 +114,7 @@ export default class Flamegraph {
99
114
  rangeMin,
100
115
  rangeMax,
101
116
  fitMode: this.fitMode,
102
- highlightQuery: this.highlightQuery,
117
+ highlightQuery,
103
118
  zoom: this.zoom,
104
119
  focusedNode: this.focusedNode,
105
120
  pxPerTick,
@@ -108,22 +123,29 @@ export default class Flamegraph {
108
123
  messages: this.messages,
109
124
  renderRects: options?.renderRects,
110
125
  renderText: options?.renderText,
126
+ renderMode: options?.renderMode,
127
+ levelStart: options?.levelStart,
128
+ levelEnd: options?.levelEnd,
129
+ startI: options?.startI,
130
+ startJ: options?.startJ,
131
+ timeBudgetMs: options?.timeBudgetMs,
132
+ skipCanvasResize: options?.skipCanvasResize,
133
+ skipDprScale: options?.skipDprScale,
134
+ devicePixelRatio: options?.devicePixelRatio,
111
135
  };
112
136
 
113
137
  const { format: viewType } = this.flamebearer;
114
138
 
115
139
  switch (viewType) {
116
140
  case 'single': {
117
- RenderCanvas({ ...props, format: 'single' });
118
- break;
141
+ return RenderCanvas({ ...props, format: 'single' });
119
142
  }
120
143
  case 'double': {
121
- RenderCanvas({
144
+ return RenderCanvas({
122
145
  ...props,
123
146
  leftTicks: this.flamebearer.leftTicks,
124
147
  rightTicks: this.flamebearer.rightTicks,
125
148
  });
126
- break;
127
149
  }
128
150
  default: {
129
151
  throw new Error(`Invalid format: '${viewType}'`);
@@ -256,7 +278,10 @@ export default class Flamegraph {
256
278
 
257
279
  private getCanvasWidth() {
258
280
  // bit of a hack, but clientWidth is not available in node-canvas
259
- return this.canvas.clientWidth || this.canvas.width;
281
+ if ('clientWidth' in this.canvas && typeof this.canvas.clientWidth === 'number') {
282
+ return this.canvas.clientWidth;
283
+ }
284
+ return this.canvas.width;
260
285
  }
261
286
 
262
287
  private isFocused() {