bootstrap.js 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. "use strict";
  2. if (process.env.PW_INSTRUMENT_MODULES) {
  3. const Module = require("module");
  4. const originalLoad = Module._load;
  5. const root = { name: "<root>", selfMs: 0, totalMs: 0, childrenMs: 0, children: [] };
  6. let current = root;
  7. const stack = [];
  8. Module._load = function(request, _parent, _isMain) {
  9. const node = { name: request, selfMs: 0, totalMs: 0, childrenMs: 0, children: [] };
  10. current.children.push(node);
  11. stack.push(current);
  12. current = node;
  13. const start = performance.now();
  14. let result;
  15. try {
  16. result = originalLoad.apply(this, arguments);
  17. } catch (e) {
  18. current = stack.pop();
  19. current.children.pop();
  20. throw e;
  21. }
  22. const duration = performance.now() - start;
  23. node.totalMs = duration;
  24. node.selfMs = Math.max(0, duration - node.childrenMs);
  25. current = stack.pop();
  26. current.childrenMs += duration;
  27. return result;
  28. };
  29. process.on("exit", () => {
  30. function printTree(node, prefix, isLast, lines2, depth) {
  31. if (node.totalMs < 1 && depth > 0)
  32. return;
  33. const connector = depth === 0 ? "" : isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
  34. const time = `${node.totalMs.toFixed(1).padStart(8)}ms`;
  35. const self = node.children.length ? ` (self: ${node.selfMs.toFixed(1)}ms)` : "";
  36. lines2.push(`${time} ${prefix}${connector}${node.name}${self}`);
  37. const childPrefix = prefix + (depth === 0 ? "" : isLast ? " " : "\u2502 ");
  38. const sorted2 = node.children.slice().sort((a, b) => b.totalMs - a.totalMs);
  39. for (let i = 0; i < sorted2.length; i++)
  40. printTree(sorted2[i], childPrefix, i === sorted2.length - 1, lines2, depth + 1);
  41. }
  42. let totalModules = 0;
  43. function count(n) {
  44. totalModules++;
  45. n.children.forEach(count);
  46. }
  47. root.children.forEach(count);
  48. const lines = [];
  49. const sorted = root.children.slice().sort((a, b) => b.totalMs - a.totalMs);
  50. for (let i = 0; i < sorted.length; i++)
  51. printTree(sorted[i], "", i === sorted.length - 1, lines, 0);
  52. const totalMs = root.children.reduce((s, c) => s + c.totalMs, 0);
  53. process.stderr.write(`
  54. --- Module load tree: ${totalModules} modules, ${totalMs.toFixed(0)}ms total ---
  55. ` + lines.join("\n") + "\n");
  56. const flat = /* @__PURE__ */ new Map();
  57. function gather(n) {
  58. const existing = flat.get(n.name);
  59. if (existing) {
  60. existing.selfMs += n.selfMs;
  61. existing.totalMs += n.totalMs;
  62. existing.count++;
  63. } else {
  64. flat.set(n.name, { selfMs: n.selfMs, totalMs: n.totalMs, count: 1 });
  65. }
  66. n.children.forEach(gather);
  67. }
  68. root.children.forEach(gather);
  69. const top50 = [...flat.entries()].sort((a, b) => b[1].selfMs - a[1].selfMs).slice(0, 50);
  70. const flatLines = top50.map(
  71. ([mod, { selfMs, totalMs: totalMs2, count: count2 }]) => `${selfMs.toFixed(1).padStart(8)}ms self ${totalMs2.toFixed(1).padStart(8)}ms total (x${String(count2).padStart(3)}) ${mod}`
  72. );
  73. process.stderr.write(`
  74. --- Top 50 modules by self time ---
  75. ` + flatLines.join("\n") + "\n");
  76. });
  77. }