Skip to content

Commit

Permalink
perf(pnp): reduce work done at runtime (#1743)
Browse files Browse the repository at this point in the history
* perf(fslib): cache decompression result

* perf(fslib): get real path from ZipFS in ZipOpenFS

* perf(pnp): throttle refreshApiEntry

* chore: versions

* chore: update pnp hook

* fix: cache realpath result instead of using zipFs.getRealPath

Co-authored-by: Maël Nison <[email protected]>
  • Loading branch information
merceyz and arcanis authored Aug 25, 2020
1 parent e97be13 commit 6c6e9de
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 13 deletions.
40 changes: 34 additions & 6 deletions .pnp.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions .yarn/versions/9dc5e5ae.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
releases:
"@yarnpkg/cli": patch
"@yarnpkg/fslib": patch
"@yarnpkg/plugin-pnp": patch
"@yarnpkg/pnp": patch

declined:
- "@yarnpkg/pnpify"
- "@yarnpkg/plugin-compat"
- "@yarnpkg/plugin-constraints"
- "@yarnpkg/plugin-dlx"
- "@yarnpkg/plugin-essentials"
- "@yarnpkg/plugin-exec"
- "@yarnpkg/plugin-file"
- "@yarnpkg/plugin-git"
- "@yarnpkg/plugin-github"
- "@yarnpkg/plugin-http"
- "@yarnpkg/plugin-init"
- "@yarnpkg/plugin-interactive-tools"
- "@yarnpkg/plugin-link"
- "@yarnpkg/plugin-node-modules"
- "@yarnpkg/plugin-npm"
- "@yarnpkg/plugin-npm-cli"
- "@yarnpkg/plugin-pack"
- "@yarnpkg/plugin-patch"
- "@yarnpkg/plugin-stage"
- "@yarnpkg/plugin-typescript"
- "@yarnpkg/plugin-version"
- "@yarnpkg/plugin-workspace-tools"
- vscode-zipfs
- "@yarnpkg/builder"
- "@yarnpkg/core"
- "@yarnpkg/doctor"
- "@yarnpkg/json-proxy"
- "@yarnpkg/shell"
12 changes: 10 additions & 2 deletions packages/yarnpkg-fslib/sources/ZipFS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -901,15 +901,23 @@ export class ZipFS extends BasePortableFakeFS {
const data = Buffer.from(memory);

if (compressionMethod === 0) {
this.fileSources.set(index, data);
return data;
} else if (opts.asyncDecompress) {
return new Promise((resolve, reject) => {
zlib.inflateRaw(data, (error, result) => {
error ? reject(error) : resolve(result);
if (error) {
reject(error);
} else {
this.fileSources.set(index, result);
resolve(result);
}
});
});
} else {
return zlib.inflateRawSync(data);
const decompressedData = zlib.inflateRawSync(data);
this.fileSources.set(index, decompressedData);
return decompressedData;
}
} finally {
this.libzip.fclose(file);
Expand Down
21 changes: 17 additions & 4 deletions packages/yarnpkg-fslib/sources/ZipOpenFS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ export class ZipOpenFS extends BasePortableFakeFS {
private readonly maxAge: number;
private readonly readOnlyArchives: boolean;

private isZip: Set<string> = new Set();
private notZip: Set<string> = new Set();
private isZip: Set<PortablePath> = new Set();
private notZip: Set<PortablePath> = new Set();
private realPaths: Map<PortablePath, PortablePath> = new Map()

constructor({libzip, baseFs = new NodeFS(), filter = null, maxOpenFiles = Infinity, readOnlyArchives = false, useCache = true, maxAge = 5000}: ZipOpenFSOptions) {
super();
Expand Down Expand Up @@ -248,15 +249,27 @@ export class ZipOpenFS extends BasePortableFakeFS {
return await this.makeCallPromise(p, async () => {
return await this.baseFs.realpathPromise(p);
}, async (zipFs, {archivePath, subPath}) => {
return this.pathUtils.join(await this.baseFs.realpathPromise(archivePath), this.pathUtils.relative(PortablePath.root, await zipFs.realpathPromise(subPath)));
let realArchivePath = this.realPaths.get(archivePath);
if (typeof realArchivePath === `undefined`) {
realArchivePath = await this.baseFs.realpathPromise(archivePath);
this.realPaths.set(archivePath, realArchivePath);
}

return this.pathUtils.join(realArchivePath, this.pathUtils.relative(PortablePath.root, await zipFs.realpathPromise(subPath)));
});
}

realpathSync(p: PortablePath) {
return this.makeCallSync(p, () => {
return this.baseFs.realpathSync(p);
}, (zipFs, {archivePath, subPath}) => {
return this.pathUtils.join(this.baseFs.realpathSync(archivePath), this.pathUtils.relative(PortablePath.root, zipFs.realpathSync(subPath)));
let realArchivePath = this.realPaths.get(archivePath);
if (typeof realArchivePath === `undefined`) {
realArchivePath = this.baseFs.realpathSync(archivePath);
this.realPaths.set(archivePath, realArchivePath);
}

return this.pathUtils.join(realArchivePath, this.pathUtils.relative(PortablePath.root, zipFs.realpathSync(subPath)));
});
}

Expand Down
2 changes: 1 addition & 1 deletion packages/yarnpkg-pnp/sources/hook.js

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions packages/yarnpkg-pnp/sources/loader/makeManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type ApiMetadata = {
cache: typeof Module._cache,
instance: PnpApi,
stats: fs.Stats,
lastRefreshCheck: number
};

export type MakeManagerOptions = {
Expand All @@ -25,6 +26,7 @@ export function makeManager(pnpapi: PnpApi, opts: MakeManagerOptions) {
cache: Module._cache,
instance: pnpapi,
stats: initialApiStats,
lastRefreshCheck: Date.now(),
}],
]);

Expand All @@ -40,6 +42,12 @@ export function makeManager(pnpapi: PnpApi, opts: MakeManagerOptions) {
}

function refreshApiEntry(pnpApiPath: PortablePath, apiEntry: ApiMetadata) {
const timeNow = Date.now();
if (timeNow - apiEntry.lastRefreshCheck < 500)
return;

apiEntry.lastRefreshCheck = timeNow;

const stats = opts.fakeFs.statSync(pnpApiPath);

if (stats.mtime > apiEntry.stats.mtime) {
Expand All @@ -62,6 +70,7 @@ export function makeManager(pnpapi: PnpApi, opts: MakeManagerOptions) {
cache: {},
instance: loadApiInstance(pnpApiPath),
stats: opts.fakeFs.statSync(pnpApiPath),
lastRefreshCheck: Date.now(),
});
}

Expand Down

0 comments on commit 6c6e9de

Please sign in to comment.