Skip to content

Commit 7ba7e1c

Browse files
committed
feat: cache intermediate results
1 parent 12cb4bf commit 7ba7e1c

File tree

1 file changed

+38
-5
lines changed

1 file changed

+38
-5
lines changed

src/file-explorer-provider.ts

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,30 @@
11
import * as vscode from 'vscode';
22
import * as fs from 'fs';
33
import * as path from 'path';
4+
45
import { encodingForModel } from 'js-tiktoken';
56
import jschardet from 'jschardet';
67
import iconv from 'iconv-lite';
78
import throttle from 'lodash.throttle';
8-
9+
import { LRUCache } from 'lru-cache';
910
import { getLabelText, getLanguageFromFilename, stripLicenseHeaders, minifyCode } from './utils';
1011
import { FileItem } from './file-item';
1112

13+
const options = {
14+
max: 5_000, // Maximum number of entries in the cache
15+
};
16+
const statCache = new LRUCache<string, fs.Stats>(options);
17+
const fileProcessCache = new LRUCache<string, { mtime: number; tokenCount: number }>(options);
18+
19+
async function getStat(filePath: string): Promise<fs.Stats> {
20+
if (statCache.has(filePath)) {
21+
return statCache.get(filePath)!;
22+
}
23+
const stat = await fs.promises.stat(filePath);
24+
statCache.set(filePath, stat);
25+
return stat;
26+
}
27+
1228
export class FileExplorerProvider implements vscode.TreeDataProvider<FileItem> {
1329
private _onDidChangeTreeData: vscode.EventEmitter<FileItem | undefined | null | void> =
1430
new vscode.EventEmitter<FileItem | undefined | null | void>();
@@ -357,7 +373,7 @@ export class FileExplorerProvider implements vscode.TreeDataProvider<FileItem> {
357373
.filter(file => !this.isExcluded(path.join(dir, file)))
358374
.map(async file => {
359375
const filePath = path.join(dir, file);
360-
const stat = await fs.promises.stat(filePath);
376+
const stat = await getStat(filePath);
361377
const isDirectory = stat.isDirectory();
362378
const isSelected = this.isSelected(filePath);
363379
const tokenCount = isDirectory
@@ -397,11 +413,21 @@ export class FileExplorerProvider implements vscode.TreeDataProvider<FileItem> {
397413
}
398414

399415
private async addFile(filePath: string) {
416+
const stat = await getStat(filePath);
417+
418+
// Check if we have a cached result for this file with the same modification time:
419+
const cached = fileProcessCache.get(filePath);
420+
if (cached && cached.mtime === stat.mtimeMs) {
421+
// Use the cached token count.
422+
this._selected.set(filePath, cached.tokenCount);
423+
return;
424+
}
425+
426+
// Read the file contents:
400427
const buffer = await fs.promises.readFile(filePath);
401428

402429
const detection = jschardet.detect(buffer) || {};
403430
let encoding = detection.encoding ? detection.encoding.toLowerCase() : 'utf-8';
404-
405431
if (encoding === 'ascii') {
406432
encoding = 'utf-8';
407433
} else if (encoding === 'utf-16' || encoding === 'utf-16le') {
@@ -417,16 +443,23 @@ export class FileExplorerProvider implements vscode.TreeDataProvider<FileItem> {
417443

418444
const config = vscode.workspace.getConfiguration('contextPrompt');
419445
const minifyEnabled = config.get<boolean>('minifyCode', false);
420-
421446
if (minifyEnabled) {
422447
const language = getLanguageFromFilename(filePath);
423448
if (language === 'typescript' || language === 'javascript') {
424449
content = await minifyCode(content);
425450
}
426451
}
427452

453+
// Compute token count from the content.:
428454
const tokenCount = this.tokenizer.encode(content).length;
455+
456+
// Store the result in the LRU cache:
457+
fileProcessCache.set(filePath, { mtime: stat.mtimeMs, tokenCount });
458+
459+
// Mark this file as selected with its token count:
429460
this._selected.set(filePath, tokenCount);
461+
462+
// Update parent directories as needed:
430463
await this.updateParentDirectorySelection(filePath);
431464
}
432465

@@ -450,7 +483,7 @@ export class FileExplorerProvider implements vscode.TreeDataProvider<FileItem> {
450483
continue;
451484
}
452485

453-
const stat = await fs.promises.stat(filePath);
486+
const stat = await getStat(filePath);
454487
if (stat.isDirectory()) {
455488
const { files, dirs } = await this.getAllChildren(filePath, token);
456489
allDirs.push(filePath, ...dirs);

0 commit comments

Comments
 (0)