@travetto/compiler 6.0.1 → 6.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/compiler",
3
- "version": "6.0.1",
3
+ "version": "6.0.2",
4
4
  "description": "The compiler infrastructure for the Travetto framework",
5
5
  "keywords": [
6
6
  "compiler",
@@ -30,11 +30,11 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@parcel/watcher": "^2.5.1",
33
- "@travetto/manifest": "^6.0.0",
34
- "@travetto/transformer": "^6.0.0"
33
+ "@travetto/manifest": "^6.0.1",
34
+ "@travetto/transformer": "^6.0.1"
35
35
  },
36
36
  "peerDependencies": {
37
- "@travetto/cli": "^6.0.0"
37
+ "@travetto/cli": "^6.0.1"
38
38
  },
39
39
  "peerDependenciesMeta": {
40
40
  "@travetto/cli": {
package/src/compiler.ts CHANGED
@@ -87,6 +87,32 @@ export class Compiler {
87
87
  CommonUtil.nonBlockingTimeout(1000).then(() => process.exit()); // Allow upto 1s to shutdown gracefully
88
88
  }
89
89
 
90
+ /**
91
+ * Log compilation statistics
92
+ */
93
+ logStatistics(metrics: CompileEmitEvent[]): void {
94
+ // Simple metrics
95
+ const durations = metrics.map(x => x.duration);
96
+ const total = durations.reduce((a, b) => a + b, 0);
97
+ const avg = total / durations.length;
98
+ const sorted = [...durations].sort((a, b) => a - b);
99
+ const median = sorted[Math.trunc(sorted.length / 2)];
100
+
101
+ // Find the 5 slowest files
102
+ const slowest = [...metrics]
103
+ .sort((a, b) => b.duration - a.duration)
104
+ .slice(0, 5)
105
+ .map(x => ({ file: x.file, duration: x.duration }));
106
+
107
+ log.debug('Compilation Statistics', {
108
+ files: metrics.length,
109
+ totalTime: total,
110
+ averageTime: Math.round(avg),
111
+ medianTime: median,
112
+ slowest
113
+ });
114
+ }
115
+
90
116
  /**
91
117
  * Compile in a single pass, only emitting dirty files
92
118
  */
@@ -101,10 +127,16 @@ export class Compiler {
101
127
  let i = 0;
102
128
  let lastSent = Date.now();
103
129
 
130
+ await emitter(files[0]); // Prime
131
+
104
132
  for (const file of files) {
133
+ const start = Date.now();
105
134
  const err = await emitter(file);
106
- const imp = file.includes('node_modules/') ? file.split('node_modules/')[1] : file;
107
- yield { file: imp, i: i += 1, err, total: files.length };
135
+ const duration = Date.now() - start;
136
+ const nodeModSep = 'node_modules/';
137
+ const nodeModIdx = file.lastIndexOf(nodeModSep);
138
+ const imp = nodeModIdx >= 0 ? file.substring(nodeModIdx + nodeModSep.length) : file;
139
+ yield { file: imp, i: i += 1, err, total: files.length, duration };
108
140
  if ((Date.now() - lastSent) > 50) { // Limit to 1 every 50ms
109
141
  lastSent = Date.now();
110
142
  EventUtil.sendEvent('progress', { total: files.length, idx: i, message: imp, operation: 'compile' });
@@ -135,6 +167,8 @@ export class Compiler {
135
167
 
136
168
  EventUtil.sendEvent('state', { state: 'compile-start' });
137
169
 
170
+ const metrics: CompileEmitEvent[] = [];
171
+
138
172
  if (this.#dirtyFiles.length) {
139
173
  for await (const ev of this.emit(this.#dirtyFiles, emitter)) {
140
174
  if (ev.err) {
@@ -142,6 +176,7 @@ export class Compiler {
142
176
  failure ??= compileError;
143
177
  EventUtil.sendEvent('log', { level: 'error', message: compileError.toString(), time: Date.now() });
144
178
  }
179
+ metrics.push(ev);
145
180
  }
146
181
  if (this.#signal.aborted) {
147
182
  log.debug('Compilation aborted');
@@ -159,6 +194,10 @@ export class Compiler {
159
194
 
160
195
  EventUtil.sendEvent('state', { state: 'compile-end' });
161
196
 
197
+ if (process.env.TRV_BUILD === 'debug' && metrics.length) {
198
+ this.logStatistics(metrics);
199
+ }
200
+
162
201
  if (this.#watch && !this.#signal.aborted) {
163
202
  log.info('Watch is ready');
164
203
 
@@ -190,7 +229,6 @@ export class Compiler {
190
229
  });
191
230
  }
192
231
  EventUtil.sendEvent('state', { state: 'watch-end' });
193
-
194
232
  } catch (err) {
195
233
  if (err instanceof Error) {
196
234
  this.#shutdown(err instanceof CompilerReset ? 'reset' : 'error', err);
package/src/types.ts CHANGED
@@ -4,7 +4,7 @@ import type { ManifestModule } from '@travetto/manifest';
4
4
 
5
5
  export type CompileEmitError = Error | readonly ts.Diagnostic[];
6
6
  export type CompileEmitter = (file: string, newProgram?: boolean) => Promise<CompileEmitError | undefined>;
7
- export type CompileEmitEvent = { file: string, i: number, total: number, err?: CompileEmitError };
7
+ export type CompileEmitEvent = { file: string, i: number, total: number, err?: CompileEmitError, duration: number };
8
8
  export type CompileStateEntry = { sourceFile: string, tscOutputFile: string, outputFile?: string, module: ManifestModule };
9
9
  export type CompilerWatchEvent = { action: 'create' | 'update' | 'delete', file: string, entry: CompileStateEntry };
10
10
  export class CompilerReset extends Error { }