Skip to content

perf: Add cache to speed up reference resolution#20

Draft
ryodine wants to merge 9 commits intofeat/shorthandfrom
perf/file-cache
Draft

perf: Add cache to speed up reference resolution#20
ryodine wants to merge 9 commits intofeat/shorthandfrom
perf/file-cache

Conversation

@ryodine
Copy link
Copy Markdown
Collaborator

@ryodine ryodine commented Mar 15, 2026

Implements file-level memoization to reduce redundant file I/O and parsing operations during !reference and !reference-all resolution. This optimization provides significant performance improvements, especially for workloads with repeated file access patterns.

In the following test, it resulted in over 100% speedup:

# main.yaml
application:
  name: test-app
  version: 1.0.0
database_config: !reference 
  path: shared.yml
  anchor: db_config
cache_config: !reference {path: shared.yml, anchor: cache_config}
full_shared: !reference {path: shared.yml}
# shared.yaml
database: &db_config
  host: localhost
  port: 5432
cache: &cache_config  
  host: redis-host
  port: 6379
settings:
  debug: false
  timeout: 30

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a file-scoped cache to reduce repeated file reads and YAML parsing during !reference / !reference-all resolution, aiming to improve performance for workloads that repeatedly touch the same files.

Changes:

  • Added a FileCache implementation for memoizing parsed YAML and (intended) reusing raw file contents.
  • Threaded an optional cache through parseYamlWithReferences* and the resolver’s recursive reference resolution.
  • Added a dedicated FileCache unit test suite.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/cache.ts Adds the cache implementation and keying scheme.
src/parser.ts Adds cache-aware fast paths and file-content reuse during parsing.
src/resolver.ts Instantiates and threads the cache through all resolution calls.
src/index.ts Exposes FileCache as a public export.
test/cache.test.ts Adds unit tests for cache behaviors and edge cases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +63 to +69
// Optimization: If we have an anchor and fileContent, also store whole file for future anchor extraction
if (anchor && fileContent) {
const wholeFileKey = this.createCacheKeyString(filePath); // No anchor = whole file
// Only store if whole file isn't already cached
if (!this.cache.has(wholeFileKey)) {
this.cache.set(wholeFileKey, { content, fileContent });
}
Comment on lines +21 to +23
*/
private createCacheKeyString(filePath: string, anchor?: string): string {
return `${filePath}|${anchor || ""}`;
Comment on lines +112 to +116
if (options?.cache) {
const cached = options.cache.get(absolutePath, options.extractAnchor);
if (cached !== undefined) {
return cached;
}
Comment on lines +121 to +126
const cachedContent = options?.cache?.getFileContent(absolutePath);
if (cachedContent) {
content = cachedContent;
} else {
content = fsSync.readFileSync(absolutePath, "utf8");
}
Comment on lines +175 to +182
// Get file content from cache or disk
let content: string;
const cachedContent = options?.cache?.getFileContent(absolutePath);
if (cachedContent) {
content = cachedContent;
} else {
content = await fs.readFile(absolutePath, "utf8");
}
Comment on lines +123 to +130
// Should have 2 entries: anchor-specific and whole file
expect(cache.size()).toBe(2);

// Anchor-specific entry
expect(cache.get(filePath, anchor)).toEqual(content);

// Whole file entry for optimization
expect(cache.get(filePath)).toEqual(content);
@ryodine
Copy link
Copy Markdown
Collaborator Author

ryodine commented Mar 15, 2026

@copilot open a new pull request to apply changes based on the comments in this thread

Copy link
Copy Markdown

Copilot AI commented Mar 15, 2026

@ryodine I've opened a new pull request, #22, to work on those changes. Once the pull request is ready, I'll request review from you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants