Skip to content

Commit 0c6733c

Browse files
committed
Tweaks to performance and benchmarking
1 parent acb9adf commit 0c6733c

File tree

16 files changed

+252
-127
lines changed

16 files changed

+252
-127
lines changed

packages/app/src/sandbox/compile.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ async function compile({
495495
showFullScreen: firstLoad,
496496
}
497497
);
498-
metrics.endMeasure('dependencies', 'Dependencies');
498+
metrics.endMeasure('dependencies', { displayName: 'Dependencies' });
499499

500500
const shouldReloadManager =
501501
(isNewCombination && !firstLoad) || manager.id !== sandboxId;
@@ -547,7 +547,7 @@ async function compile({
547547
await manager.verifyTreeTranspiled();
548548
await manager.transpileModules(managerModuleToTranspile);
549549

550-
metrics.endMeasure('transpilation', 'Transpilation');
550+
metrics.endMeasure('transpilation', { displayName: 'Transpilation' });
551551

552552
dispatch({ type: 'status', status: 'evaluating' });
553553
manager.setStage('evaluation');
@@ -612,14 +612,16 @@ async function compile({
612612

613613
metrics.measure('external-resources');
614614
await handleExternalResources(externalResources);
615-
metrics.endMeasure('external-resources', 'External Resources');
615+
metrics.endMeasure('external-resources', {
616+
displayName: 'External Resources',
617+
});
616618

617619
const oldHTML = document.body.innerHTML;
618620
metrics.measure('evaluation');
619621
const evalled = manager.evaluateModule(managerModuleToTranspile, {
620622
force: isModuleView,
621623
});
622-
metrics.endMeasure('evaluation', 'Evaluation');
624+
metrics.endMeasure('evaluation', { displayName: 'Evaluation' });
623625

624626
const domChanged =
625627
!manager.preset.htmlDisabled && oldHTML !== document.body.innerHTML;
@@ -669,8 +671,8 @@ async function compile({
669671

670672
debug(`Total time: ${Date.now() - startTime}ms`);
671673

672-
metrics.endMeasure('compilation', 'Compilation');
673-
metrics.endMeasure('total', 'Total', { lastTime: 0 });
674+
metrics.endMeasure('compilation', { displayName: 'Compilation' });
675+
metrics.endMeasure('total', { displayName: 'Total', lastTime: 0 });
674676
dispatch({
675677
type: 'success',
676678
});

packages/app/src/sandbox/eval/manager.ts

Lines changed: 90 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { packageFilter } from './utils/resolve-utils';
2929
import { ignoreNextCache, deleteAPICache, clearIndexedDBCache } from './cache';
3030
import { shouldTranspile } from './transpilers/babel/check';
3131
import { splitQueryFromPath } from './utils/query-path';
32+
import { measure, endMeasure } from '../utils/metrics';
3233

3334
declare const BrowserFS: any;
3435

@@ -598,102 +599,106 @@ export default class Manager {
598599
currentPath: string,
599600
defaultExtensions = ['js', 'jsx', 'json']
600601
): Promise<Module> {
601-
return new Promise(promiseResolve => {
602-
const dirredPath = pathUtils.dirname(currentPath);
603-
if (this.cachedPaths[dirredPath] === undefined) {
604-
this.cachedPaths[dirredPath] = {};
605-
}
602+
const dirredPath = pathUtils.dirname(currentPath);
603+
if (this.cachedPaths[dirredPath] === undefined) {
604+
this.cachedPaths[dirredPath] = {};
605+
}
606606

607-
const cachedPath = this.cachedPaths[dirredPath][path];
607+
const cachedPath = this.cachedPaths[dirredPath][path];
608608

609-
let resolvedPath;
609+
if (cachedPath) {
610+
return Promise.resolve(this.transpiledModules[cachedPath].module);
611+
}
610612

611-
if (cachedPath) {
612-
resolvedPath = cachedPath;
613-
} else {
614-
const presetAliasedPath = this.getPresetAliasedPath(path);
613+
const measureKey = `resolve-async-${path}:${currentPath}`;
614+
return new Promise((promiseResolve, promiseReject) => {
615+
measure(measureKey);
616+
const presetAliasedPath = this.getPresetAliasedPath(path);
615617

616-
const aliasedPath = this.getAliasedDependencyPath(
617-
presetAliasedPath,
618-
currentPath
619-
);
620-
const shimmedPath = coreLibraries[aliasedPath] || aliasedPath;
618+
const aliasedPath = this.getAliasedDependencyPath(
619+
presetAliasedPath,
620+
currentPath
621+
);
622+
const shimmedPath = coreLibraries[aliasedPath] || aliasedPath;
621623

622-
if (NODE_LIBS.indexOf(shimmedPath) > -1) {
623-
this.cachedPaths[dirredPath][path] = shimmedPath;
624-
promiseResolve(getShimmedModuleFromPath(currentPath, path));
625-
return;
626-
}
624+
if (NODE_LIBS.indexOf(shimmedPath) > -1) {
625+
this.cachedPaths[dirredPath][path] = shimmedPath;
626+
promiseResolve(getShimmedModuleFromPath(currentPath, path));
627+
return;
628+
}
627629

628-
try {
629-
resolve(
630-
shimmedPath,
631-
{
632-
filename: currentPath,
633-
extensions: defaultExtensions.map(ext => '.' + ext),
634-
isFile: this.isFile,
635-
readFileSync: this.readFileSync,
636-
packageFilter,
637-
moduleDirectory: this.getModuleDirectories(),
638-
},
639-
(err, foundPath) => {
640-
if (err) {
641-
throw err;
642-
}
630+
resolve(
631+
shimmedPath,
632+
{
633+
filename: currentPath,
634+
extensions: defaultExtensions.map(ext => '.' + ext),
635+
isFile: this.isFile,
636+
readFileSync: this.readFileSync,
637+
packageFilter,
638+
moduleDirectory: this.getModuleDirectories(),
639+
},
640+
(err, foundPath) => {
641+
endMeasure(measureKey, { silent: true });
642+
if (err) {
643+
if (
644+
this.cachedPaths[dirredPath] &&
645+
this.cachedPaths[dirredPath][path]
646+
) {
647+
delete this.cachedPaths[dirredPath][path];
648+
}
643649

644-
this.cachedPaths[dirredPath][path] = foundPath;
650+
let connectedPath = shimmedPath;
651+
if (connectedPath.indexOf('/node_modules') !== 0) {
652+
connectedPath = /^(\w|@\w)/.test(shimmedPath)
653+
? pathUtils.join('/node_modules', shimmedPath)
654+
: pathUtils.join(pathUtils.dirname(currentPath), shimmedPath);
655+
}
645656

646-
if (foundPath === '//empty.js') {
647-
promiseResolve(getShimmedModuleFromPath(currentPath, path));
648-
return;
649-
}
657+
const isDependency = connectedPath.includes('/node_modules/');
650658

651-
if (!this.transpiledModules[foundPath]) {
652-
this.readFileSync(foundPath, code => {
653-
this.addModule({ path: foundPath, code });
654-
promiseResolve(this.transpiledModules[foundPath].module);
655-
});
656-
} else {
657-
promiseResolve(this.transpiledModules[foundPath].module);
658-
}
659+
connectedPath = connectedPath.replace('/node_modules/', '');
660+
661+
if (!isDependency) {
662+
promiseReject(
663+
new ModuleNotFoundError(shimmedPath, false, currentPath)
664+
);
659665
}
660-
);
661-
} catch (e) {
662-
if (
663-
this.cachedPaths[dirredPath] &&
664-
this.cachedPaths[dirredPath][path]
665-
) {
666-
delete this.cachedPaths[dirredPath][path];
667-
}
668666

669-
let connectedPath = shimmedPath;
670-
if (connectedPath.indexOf('/node_modules') !== 0) {
671-
connectedPath = /^(\w|@\w)/.test(shimmedPath)
672-
? pathUtils.join('/node_modules', shimmedPath)
673-
: pathUtils.join(pathUtils.dirname(currentPath), shimmedPath);
674-
}
667+
const dependencyName = getDependencyName(connectedPath);
668+
669+
if (
670+
this.manifest.dependencies.find(d => d.name === dependencyName) ||
671+
this.manifest.dependencyDependencies[dependencyName]
672+
) {
673+
promiseReject(
674+
new ModuleNotFoundError(connectedPath, true, currentPath)
675+
);
676+
} else {
677+
promiseReject(
678+
new DependencyNotFoundError(connectedPath, currentPath)
679+
);
680+
}
675681

676-
const isDependency = connectedPath.includes('/node_modules/');
682+
return;
683+
}
677684

678-
connectedPath = connectedPath.replace('/node_modules/', '');
685+
this.cachedPaths[dirredPath][path] = foundPath;
679686

680-
if (!isDependency) {
681-
throw new ModuleNotFoundError(shimmedPath, false, currentPath);
687+
if (foundPath === '//empty.js') {
688+
promiseResolve(getShimmedModuleFromPath(currentPath, path));
689+
return;
682690
}
683691

684-
const dependencyName = getDependencyName(connectedPath);
685-
686-
if (
687-
this.manifest.dependencies.find(d => d.name === dependencyName) ||
688-
this.manifest.dependencyDependencies[dependencyName]
689-
) {
690-
throw new ModuleNotFoundError(connectedPath, true, currentPath);
692+
if (!this.transpiledModules[foundPath]) {
693+
this.readFileSync(foundPath, code => {
694+
this.addModule({ path: foundPath, code });
695+
promiseResolve(this.transpiledModules[foundPath].module);
696+
});
691697
} else {
692-
throw new DependencyNotFoundError(connectedPath, currentPath);
698+
promiseResolve(this.transpiledModules[foundPath].module);
693699
}
694700
}
695-
}
696-
promiseResolve(this.transpiledModules[resolvedPath].module);
701+
);
697702
});
698703
}
699704

@@ -715,6 +720,8 @@ export default class Manager {
715720
if (cachedPath && this.transpiledModules[cachedPath]) {
716721
resolvedPath = cachedPath;
717722
} else {
723+
const measureKey = `resolve-sync-${path}:${currentPath}`;
724+
measure(measureKey);
718725
const presetAliasedPath = this.getPresetAliasedPath(path);
719726

720727
const aliasedPath = this.getAliasedDependencyPath(
@@ -737,6 +744,7 @@ export default class Manager {
737744
packageFilter,
738745
moduleDirectory: this.getModuleDirectories(),
739746
});
747+
endMeasure(measureKey, { silent: true });
740748

741749
this.cachedPaths[dirredPath][path] = resolvedPath;
742750

@@ -823,12 +831,11 @@ export default class Manager {
823831
const tModule =
824832
currentTModule || this.getTranspiledModule(this.modules['/package.json']); // Get arbitrary file from root
825833
try {
826-
return Promise.resolve(
827-
this.resolveTranspiledModule(
828-
path,
829-
tModule.module.path,
830-
ignoredExtensions
831-
)
834+
return this.resolveTranspiledModule(
835+
path,
836+
tModule.module.path,
837+
ignoredExtensions,
838+
true
832839
);
833840
} catch (e) {
834841
if (e.type === 'module-not-found' && e.isDependency) {

packages/app/src/sandbox/eval/presets/svelte/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const babelOptions = {
1919
export default function initialize() {
2020
const sveltePreset = new Preset('svelte', ['js', 'jsx', 'svelte'], {});
2121

22-
sveltePreset.registerTranspiler(module => /\.jsx?$/.test(module.path), [
22+
sveltePreset.registerTranspiler(module => /\.m?jsx?$/.test(module.path), [
2323
{ transpiler: babelTranspiler, options: babelOptions },
2424
]);
2525

packages/app/src/sandbox/eval/transpiled-module.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import Manager, { HMRStatus } from './manager';
2222
import HMR from './hmr';
2323
import { splitQueryFromPath } from './utils/query-path';
2424
import delay from '../utils/delay';
25+
import { measure, endMeasure } from '../utils/metrics';
2526

2627
declare const BrowserFS: any;
2728

@@ -325,7 +326,7 @@ export default class TranspiledModule {
325326
);
326327
}
327328

328-
addDependency(
329+
async addDependency(
329330
manager: Manager,
330331
depPath: string,
331332
options: {
@@ -339,7 +340,7 @@ export default class TranspiledModule {
339340
}
340341

341342
try {
342-
const tModule = manager.resolveTranspiledModule(
343+
const tModule = await manager.resolveTranspiledModule(
343344
depPath,
344345
options && options.isAbsolute ? '/' : this.module.path
345346
);
@@ -610,7 +611,6 @@ export default class TranspiledModule {
610611
} else {
611612
const transpilers = manager.preset.getLoaders(this.module, this.query);
612613

613-
const startTime = Date.now();
614614
for (let i = 0; i < transpilers.length; i += 1) {
615615
const transpilerConfig = transpilers[i];
616616
const loaderContext = this.getLoaderContext(
@@ -623,12 +623,15 @@ export default class TranspiledModule {
623623
.concat([this.module.path])
624624
.join('!');
625625

626+
const measureKey = `transpile-${transpilerConfig.transpiler.name}-${this.module.path}`;
626627
try {
628+
measure(measureKey);
627629
const {
628630
transpiledCode,
629631
sourceMap,
630632
// eslint-disable-next-line no-await-in-loop
631633
} = await transpilerConfig.transpiler.transpile(code, loaderContext);
634+
endMeasure(measureKey, { silent: true });
632635

633636
if (this.errors.length) {
634637
throw this.errors[0];
@@ -649,7 +652,6 @@ export default class TranspiledModule {
649652
throw e;
650653
}
651654
}
652-
debug(`Transpiled '${this.getId()}' in ${Date.now() - startTime}ms`);
653655

654656
this.logWarnings();
655657
}
@@ -879,8 +881,8 @@ export default class TranspiledModule {
879881
} else {
880882
const paths = typeof path === 'string' ? [path] : path;
881883

882-
paths.forEach(p => {
883-
const tModule = manager.resolveTranspiledModule(
884+
paths.forEach(async p => {
885+
const tModule = await manager.resolveTranspiledModule(
884886
p,
885887
this.module.path
886888
);
@@ -901,8 +903,8 @@ export default class TranspiledModule {
901903
} else {
902904
const paths = typeof path === 'string' ? [path] : path;
903905

904-
paths.forEach(p => {
905-
const tModule = manager.resolveTranspiledModule(
906+
paths.forEach(async p => {
907+
const tModule = await manager.resolveTranspiledModule(
906908
p,
907909
this.module.path
908910
);

packages/app/src/sandbox/eval/transpilers/babel/convert-esmodule/__snapshots__/index.test.ts.snap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,8 @@ function $csb__default() {}
156156
`;
157157

158158
exports[`convert-esmodule ignores comments 1`] = `""`;
159+
160+
exports[`convert-esmodule parses and writes chars with linebreaks 1`] = `
161+
"var WS_CHARS = \\"u2000- 

   \\";
162+
"
163+
`;

packages/app/src/sandbox/eval/transpilers/babel/convert-esmodule/index.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,12 @@ describe('convert-esmodule', () => {
128128
expect(convertEsModule(code)).toMatchSnapshot();
129129
});
130130

131+
it('parses and writes chars with linebreaks', () => {
132+
const code =
133+
"var WS_CHARS = 'u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff'";
134+
expect(convertEsModule(code)).toMatchSnapshot();
135+
});
136+
131137
it('has good perf', () => {
132138
/* eslint-disable */
133139
const code = require('./big-file');

0 commit comments

Comments
 (0)