mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
The relative resolve cache was keyed by a concatenated
${parent.path}\x00${request} string, allocating a new key for every
require() call including fully cached ones. Key the cache by the
parent directory first (a Map keyed by the already-retained
module.path string) and then by the request (a dictionary object,
whose property access internalizes dynamically-constructed
specifiers). Faster on every measured workload shape and slightly
smaller in memory, since the concatenated keys are no longer
retained.
Signed-off-by: Sam Attard <sattard@anthropic.com>
PR-URL: https://github.com/nodejs/node/pull/63884
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
59 lines
1.8 KiB
JavaScript
59 lines
1.8 KiB
JavaScript
'use strict';
|
|
|
|
// Checks that Module._load() only creates a relative resolve cache entry for
|
|
// the parent directory when there is a resolved filename to store in it.
|
|
|
|
require('../common');
|
|
const assert = require('assert');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const Module = require('module');
|
|
const tmpdir = require('../common/tmpdir');
|
|
|
|
tmpdir.refresh();
|
|
|
|
let uniqueId = 0;
|
|
|
|
function createParent() {
|
|
const dir = tmpdir.resolve(`dir-${uniqueId++}`);
|
|
fs.mkdirSync(dir);
|
|
const parent = new Module(path.join(dir, 'parent.js'));
|
|
parent.filename = parent.id;
|
|
parent.paths = Module._nodeModulePaths(dir);
|
|
let pathReads = 0;
|
|
Object.defineProperty(parent, 'path', {
|
|
__proto__: null,
|
|
get() {
|
|
pathReads++;
|
|
return dir;
|
|
},
|
|
});
|
|
return { dir, parent, getPathReads: () => pathReads };
|
|
}
|
|
|
|
// Builtins return before the relative resolve cache is populated, so the
|
|
// parent directory should only be looked up, not also used to create a bucket.
|
|
for (const request of ['node:path', 'path']) {
|
|
const { parent, getPathReads } = createParent();
|
|
assert.strictEqual(Module._load(request, parent, false), path);
|
|
assert.strictEqual(getPathReads(), 1);
|
|
}
|
|
|
|
// Same for resolutions that throw.
|
|
{
|
|
const { parent, getPathReads } = createParent();
|
|
assert.throws(() => Module._load('./missing', parent, false),
|
|
{ code: 'MODULE_NOT_FOUND' });
|
|
assert.strictEqual(getPathReads(), 1);
|
|
}
|
|
|
|
// A successful load populates the cache, and the second load hits it.
|
|
{
|
|
const { dir, parent, getPathReads } = createParent();
|
|
fs.writeFileSync(path.join(dir, 'child.js'), 'module.exports = {};');
|
|
const first = Module._load('./child', parent, false);
|
|
assert.strictEqual(getPathReads(), 1);
|
|
assert.strictEqual(Module._load('./child', parent, false), first);
|
|
assert.strictEqual(getPathReads(), 2);
|
|
}
|