@ticket-gate/react 0.0.0 → 0.1.0-rc.1
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/LICENSE +202 -0
- package/README.md +89 -0
- package/compiler.mjs +391 -0
- package/index.mjs +27 -0
- package/package.json +21 -1
- package/profile.mjs +27 -0
- package/profiler/capture.mjs +36 -0
- package/profiler/cli.mjs +206 -0
- package/profiler/nightly-child.mjs +26 -0
- package/profiler/nightly.mjs +202 -0
- package/profiler/stats.mjs +130 -0
- package/profiler/trace.mjs +85 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Chrome trace reduction for the React profiler. No project literal: the
|
|
2
|
+
// component names and the build hints come from the caller.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Reduces a Chrome trace to the render numbers. `traceEvents` (or a bare array) of
|
|
6
|
+
* `TimeStamp` events whose `args.data` carries React's track, message and start/end (us).
|
|
7
|
+
*/
|
|
8
|
+
export function analyse(trace, names) {
|
|
9
|
+
const events = (Array.isArray(trace) ? trace : trace.traceEvents)
|
|
10
|
+
.filter((e) => e.name === 'TimeStamp' && e.args?.data)
|
|
11
|
+
.map((e) => e.args.data);
|
|
12
|
+
const ms = (d) => (d.end - d.start) / 1000;
|
|
13
|
+
const sched = events
|
|
14
|
+
.filter((d) => d.trackGroup === 'Scheduler ⚛' && d.end > d.start)
|
|
15
|
+
.sort((a, b) => a.start - b.start);
|
|
16
|
+
const commits = sched.filter((d) => d.message === 'Commit');
|
|
17
|
+
const renders = sched.filter((d) => d.message === 'Render');
|
|
18
|
+
// A commit's cost: itself plus every Render on its lane since that lane's previous commit.
|
|
19
|
+
const lastCommitEnd = {};
|
|
20
|
+
let slowest = 0;
|
|
21
|
+
for (const c of commits) {
|
|
22
|
+
const since = lastCommitEnd[c.track] ?? -Infinity;
|
|
23
|
+
const own = renders.filter(
|
|
24
|
+
(r) => r.track === c.track && r.start >= since && r.end <= c.start + 1,
|
|
25
|
+
);
|
|
26
|
+
slowest = Math.max(slowest, ms(c) + own.reduce((s, r) => s + ms(r), 0));
|
|
27
|
+
lastCommitEnd[c.track] = c.end;
|
|
28
|
+
}
|
|
29
|
+
const renderMs = renders.reduce((s, r) => s + ms(r), 0);
|
|
30
|
+
const commitMs = commits.reduce((s, c) => s + ms(c), 0);
|
|
31
|
+
// Effect entries use the `secondary*` colours; renders use `primary*` / `tertiary*`.
|
|
32
|
+
const rendered = events.filter(
|
|
33
|
+
(d) =>
|
|
34
|
+
d.track === 'Components ⚛' && !String(d.color).startsWith('secondary'),
|
|
35
|
+
);
|
|
36
|
+
const counts = Object.fromEntries(
|
|
37
|
+
names.map((name) => [
|
|
38
|
+
name,
|
|
39
|
+
rendered.filter((d) =>
|
|
40
|
+
new RegExp(`(^|\\()${name}(\\)|$)`).test(d.message),
|
|
41
|
+
).length,
|
|
42
|
+
]),
|
|
43
|
+
);
|
|
44
|
+
return {
|
|
45
|
+
commits: commits.length,
|
|
46
|
+
totalRenderMs: round(renderMs + commitMs),
|
|
47
|
+
renderMs: round(renderMs),
|
|
48
|
+
commitMs: round(commitMs),
|
|
49
|
+
slowestCommitMs: round(slowest),
|
|
50
|
+
...counts,
|
|
51
|
+
componentRendersAll: rendered.length,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const round = (n) => Math.round(n * 10) / 10;
|
|
56
|
+
|
|
57
|
+
/** The three guard messages. `build` is { command, unmangle }, `messages` is { expected }. */
|
|
58
|
+
export const problemHints = ({ build, messages }) => ({
|
|
59
|
+
noCommit: `no React Commit in the trace: not a profiling build. Build with \`${build.command}\`, or run with --build.`,
|
|
60
|
+
noHook:
|
|
61
|
+
'Commits but no Components track: the __REACT_DEVTOOLS_GLOBAL_HOOK__ stub was not installed before React loaded.',
|
|
62
|
+
mangled: `the Components track has none of the expected component names (${messages.expected}): component names are mangled. Build with ${build.unmangle}, or run with --build.`,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
/** r = analyse(...). Returns one hints value, or null for a usable trace. */
|
|
66
|
+
export function traceProblem(r, names, hints) {
|
|
67
|
+
if (r.commits === 0) return hints.noCommit;
|
|
68
|
+
if (r.componentRendersAll === 0) return hints.noHook;
|
|
69
|
+
if (names.every((name) => r[name] === 0)) return hints.mangled;
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** analyse + guard: throws the guard message so the run exits 1 instead of printing zeros. */
|
|
74
|
+
export function reduceRun(trace, names, hints) {
|
|
75
|
+
const result = analyse(trace, names);
|
|
76
|
+
const problem = traceProblem(result, names, hints);
|
|
77
|
+
if (problem !== null) throw new Error(problem);
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function median(xs) {
|
|
82
|
+
const s = [...xs].sort((a, b) => a - b);
|
|
83
|
+
const mid = Math.floor(s.length / 2);
|
|
84
|
+
return s.length % 2 === 1 ? s[mid] : round((s[mid - 1] + s[mid]) / 2);
|
|
85
|
+
}
|