UNPKG

5.11 kBJavaScriptView Raw
1const MS_IN_MINUTE = 60000;
2const MS_IN_SECOND = 1000;
3
4const chalk = require("chalk");
5const { fg, bg } = require("./colours");
6const { groupBy, getAverages, getTotalActiveTime } = require("./utils");
7
8const humanTime = (ms, options = {}) => {
9 if (options.verbose) {
10 return ms.toLocaleString() + " ms";
11 }
12
13 const minutes = Math.floor(ms / MS_IN_MINUTE);
14 const secondsRaw = (ms - minutes * MS_IN_MINUTE) / MS_IN_SECOND;
15 const secondsWhole = Math.floor(secondsRaw);
16 const remainderPrecision = secondsWhole > 0 ? 2 : 3;
17 const secondsRemainder = Math.min(secondsRaw - secondsWhole, 0.99);
18 const seconds =
19 secondsWhole +
20 secondsRemainder
21 .toPrecision(remainderPrecision)
22 .replace(/^0/, "")
23 .replace(/0+$/, "")
24 .replace(/^\.$/, "");
25
26 let time = "";
27
28 if (minutes > 0) time += minutes + " min" + (minutes > 1 ? "s" : "") + ", ";
29 time += seconds + " secs";
30
31 return time;
32};
33
34const smpTag = () => bg(" SMP ") + " ⏱ ";
35module.exports.smpTag = smpTag;
36
37module.exports.getHumanOutput = (outputObj, options = {}) => {
38 const hT = (x) => humanTime(x, options);
39 let output = "\n\n" + smpTag() + "\n";
40
41 if (outputObj.misc) {
42 output +=
43 "General output time took " +
44 fg(hT(outputObj.misc.compileTime, options), outputObj.misc.compileTime);
45 output += "\n\n";
46 }
47 if (outputObj.plugins) {
48 output += smpTag() + "Plugins\n";
49 Object.keys(outputObj.plugins)
50 .sort(
51 (name1, name2) => outputObj.plugins[name2] - outputObj.plugins[name1]
52 )
53 .forEach((pluginName) => {
54 output +=
55 chalk.bold(pluginName) +
56 " took " +
57 fg(hT(outputObj.plugins[pluginName]), outputObj.plugins[pluginName]);
58 output += "\n";
59 });
60 output += "\n";
61 }
62 if (outputObj.loaders) {
63 output += smpTag() + "Loaders\n";
64 outputObj.loaders.build
65 .sort((obj1, obj2) => obj2.activeTime - obj1.activeTime)
66 .forEach((loaderObj) => {
67 output +=
68 loaderObj.loaders.map(fg).join(", and \n") +
69 " took " +
70 fg(hT(loaderObj.activeTime), loaderObj.activeTime) +
71 "\n";
72
73 let xEqualsY = [];
74 if (options.verbose) {
75 xEqualsY.push(["median", hT(loaderObj.averages.median)]);
76 xEqualsY.push(["mean", hT(loaderObj.averages.mean)]);
77 if (typeof loaderObj.averages.variance === "number")
78 xEqualsY.push(["s.d.", hT(Math.sqrt(loaderObj.averages.variance))]);
79 xEqualsY.push([
80 "range",
81 "(" +
82 hT(loaderObj.averages.range.start) +
83 " --> " +
84 hT(loaderObj.averages.range.end) +
85 ")",
86 ]);
87 }
88
89 if (loaderObj.loaders.length > 1) {
90 Object.keys(loaderObj.subLoadersTime).forEach((subLoader) => {
91 xEqualsY.push([subLoader, hT(loaderObj.subLoadersTime[subLoader])]);
92 });
93 }
94
95 xEqualsY.push(["module count", loaderObj.averages.dataPoints]);
96
97 if (options.loaderTopFiles) {
98 const loopLen = Math.min(
99 loaderObj.rawStartEnds.length,
100 options.loaderTopFiles
101 );
102 for (let i = 0; i < loopLen; i++) {
103 const rawItem = loaderObj.rawStartEnds[i];
104 xEqualsY.push([rawItem.name, hT(rawItem.end - rawItem.start)]);
105 }
106 }
107
108 const maxXLength = xEqualsY.reduce(
109 (acc, cur) => Math.max(acc, cur[0].length),
110 0
111 );
112 xEqualsY.forEach((xY) => {
113 const padEnd = maxXLength - xY[0].length;
114 output += " " + xY[0] + " ".repeat(padEnd) + " = " + xY[1] + "\n";
115 });
116 });
117 }
118
119 output += "\n\n";
120
121 return output;
122};
123
124module.exports.getMiscOutput = (data) => ({
125 compileTime: data.compile[0].end - data.compile[0].start,
126});
127
128module.exports.getPluginsOutput = (data) =>
129 Object.keys(data).reduce((acc, key) => {
130 const inData = data[key];
131
132 const startEndsByName = groupBy("name", inData);
133
134 return startEndsByName.reduce((innerAcc, startEnds) => {
135 innerAcc[startEnds[0].name] =
136 (innerAcc[startEnds[0].name] || 0) + getTotalActiveTime(startEnds);
137 return innerAcc;
138 }, acc);
139 }, {});
140
141module.exports.getLoadersOutput = (data) => {
142 const startEndsByLoader = groupBy("loaders", data.build);
143 const allSubLoaders = data["build-specific"] || [];
144
145 const buildData = startEndsByLoader.map((startEnds) => {
146 const averages = getAverages(startEnds);
147 const activeTime = getTotalActiveTime(startEnds);
148 const subLoaders = groupBy(
149 "loader",
150 allSubLoaders.filter((l) => startEnds.find((x) => x.name === l.name))
151 );
152 const subLoadersActiveTime = subLoaders.reduce((acc, loaders) => {
153 acc[loaders[0].loader] = getTotalActiveTime(loaders);
154 return acc;
155 }, {});
156
157 return {
158 averages,
159 activeTime,
160 loaders: startEnds[0].loaders,
161 subLoadersTime: subLoadersActiveTime,
162 rawStartEnds: startEnds.sort(
163 (a, b) => b.end - b.start - (a.end - a.start)
164 ),
165 };
166 });
167
168 return { build: buildData };
169};