mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-30 06:42:43 +00:00
perf(r): look up a wildcard import's target file in a per-pass index
expandRWildcardNames scanned every parsed file with find() for each library() edge (450,000 edges over 3,000 files took 5.9 s). Build the module-scope lookup once per pass, as the C, C++ and Python providers do.
This commit is contained in:
parent
c63dcc1278
commit
f78f7cbc2e
2 changed files with 38 additions and 1 deletions
|
|
@ -34,6 +34,7 @@ import type { GraphNodeLookup } from '../../scope-resolution/graph-bridge/node-l
|
|||
import type { KnowledgeGraph } from '../../../graph/types.js';
|
||||
import { generateId } from '../../../../lib/utils.js';
|
||||
import { loadRPackageConfig } from './package-config.js';
|
||||
import { perFileSet } from '../../import-resolvers/per-file-set.js';
|
||||
import { resolveRImportTarget } from '../../import-resolvers/r.js';
|
||||
import {
|
||||
isRGlobalNameFallbackPlausible,
|
||||
|
|
@ -103,6 +104,23 @@ function emitRVirtualHeritageEdges(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* `moduleScope` → its `ParsedFile`, built once per pass and keyed on the identity of the pass's
|
||||
* `parsedFiles` array, which finalize passes unchanged to every `expandsWildcardTo` call. The
|
||||
* lookup used to be `parsedFiles.find`, one scan of all files per `library()` edge: 450,000 edges
|
||||
* over 3,000 files took 5.9 s. As in the C, C++ and Python providers, the first file wins on a
|
||||
* repeated scope, as `find` did.
|
||||
*/
|
||||
const parsedFileByModuleScope = perFileSet(
|
||||
(parsedFiles: readonly ParsedFile[]): Map<ScopeId, ParsedFile> => {
|
||||
const index = new Map<ScopeId, ParsedFile>();
|
||||
for (const parsed of parsedFiles) {
|
||||
if (!index.has(parsed.moduleScope)) index.set(parsed.moduleScope, parsed);
|
||||
}
|
||||
return index;
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Enumerate all top-level names exported from a target module scope's file
|
||||
* (module-scope function and class bindings; functions nested in another function are not).
|
||||
|
|
@ -126,7 +144,7 @@ export function expandRWildcardNames(
|
|||
targetModuleScope: ScopeId,
|
||||
parsedFiles: readonly ParsedFile[],
|
||||
): readonly string[] {
|
||||
const target = parsedFiles.find((p) => p.moduleScope === targetModuleScope);
|
||||
const target = parsedFileByModuleScope(parsedFiles).get(targetModuleScope);
|
||||
if (target === undefined) return [];
|
||||
const { names: topLevel, dottedTails } = rFileTopLevel(target);
|
||||
const seen = new Set<string>();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
rIsCallableVisibleFromCaller,
|
||||
rScopeResolver,
|
||||
} from '../../../../src/core/ingestion/languages/r/scope-resolver.js';
|
||||
import { countedParsedFiles } from '../../../helpers/counting-file-set.js';
|
||||
|
||||
function parse(src: string, filePath: string): ParsedFile {
|
||||
const parsed = extractParsedFile(rProvider, src, filePath);
|
||||
|
|
@ -146,3 +147,21 @@ describe('expandRWildcardNames', () => {
|
|||
expect(expandRWildcardNames('scope:missing' as never, [a])).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('expandRWildcardNames: the module-scope lookup is built once per pass', () => {
|
||||
it('reads each parsed file once however many wildcard edges ask', () => {
|
||||
// `parsedFiles.find` per edge read the files up to the match every time. Counted element
|
||||
// reads, not wall time: the figure depends on the file count and the number of passes only.
|
||||
const paths = Array.from({ length: 200 }, (_, i) => `pkg/R/f${i}.R`);
|
||||
const { parsedFiles, reads } = countedParsedFiles(paths);
|
||||
for (let edge = 0; edge < 1_000; edge++) {
|
||||
expandRWildcardNames(`module:${paths[(edge * 7) % paths.length]}`, parsedFiles);
|
||||
}
|
||||
expect(reads()).toBe(paths.length);
|
||||
});
|
||||
|
||||
it('answers a scope no file owns with nothing', () => {
|
||||
const { parsedFiles } = countedParsedFiles(['pkg/R/a.R']);
|
||||
expect(expandRWildcardNames('module:absent' as never, parsedFiles)).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue