Skip to content

Commit 797f061

Browse files
committed
perf: dynamische Cache‑Konfiguration, Cache‑Statistiken & Management‑Befehle 📈
- Automatische Ermittlung von max. Cache‑Größe und max. Dateigröße basierend auf verfügbarem Heap - Neue Einstellungen: cacheMaxFiles, cacheMaxFileSize, enableCacheStatistics und Befehl "Show Cache Statistics" - Cache-Invalidierung, Optimierung bei hohem Speicherdruck und zugehörige Changelog/package.json-Updates
1 parent d13d14c commit 797f061

File tree

3 files changed

+137
-10
lines changed

3 files changed

+137
-10
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ All notable changes to the "magento-log-viewer" extension will be documented in
44

55
## Next release
66

7+
### [1.16.0] - TBD
8+
9+
- perf: Implemented dynamic cache configuration based on available system memory
10+
- perf: Added intelligent cache size management with automatic optimization under memory pressure
11+
- perf: Enhanced cache statistics and monitoring capabilities for better performance insights
12+
- feat: Added user-configurable cache settings: `cacheMaxFiles`, `cacheMaxFileSize`, `enableCacheStatistics`
13+
- feat: Added "Show Cache Statistics" command for real-time cache monitoring
14+
- feat: Cache now automatically scales from 20-100 files and 1-10MB based on available memory
15+
- fix: Cache management now removes multiple old entries efficiently instead of one-by-one cleanup
16+
- fix: Added automatic cache optimization when system memory usage exceeds 80%
17+
- fix: Improved memory usage estimation and monitoring for cached file contents
18+
719
---
820

921
## Latest Release

package.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@
8686
"command": "magento-log-viewer.clearSearch",
8787
"title": "Clear Search",
8888
"icon": "$(clear-all)"
89+
},
90+
{
91+
"command": "magento-log-viewer.showCacheStatistics",
92+
"title": "Show Cache Statistics",
93+
"icon": "$(info)"
8994
}
9095
],
9196
"configuration": {
@@ -126,6 +131,28 @@
126131
"default": false,
127132
"description": "Enable regular expression search in log entries",
128133
"scope": "resource"
134+
},
135+
"magentoLogViewer.cacheMaxFiles": {
136+
"type": "number",
137+
"default": 0,
138+
"minimum": 0,
139+
"maximum": 500,
140+
"description": "Maximum number of files to cache in memory (0 = automatic based on available memory)",
141+
"scope": "resource"
142+
},
143+
"magentoLogViewer.cacheMaxFileSize": {
144+
"type": "number",
145+
"default": 0,
146+
"minimum": 0,
147+
"maximum": 100,
148+
"description": "Maximum file size to cache in MB (0 = automatic based on available memory)",
149+
"scope": "resource"
150+
},
151+
"magentoLogViewer.enableCacheStatistics": {
152+
"type": "boolean",
153+
"default": false,
154+
"description": "Show cache statistics in developer console (useful for debugging performance)",
155+
"scope": "resource"
129156
}
130157
}
131158
},
@@ -228,6 +255,11 @@
228255
"when": "view == logFiles && magentoLogViewer.hasMagentoRoot",
229256
"group": "navigation@4"
230257
},
258+
{
259+
"command": "magento-log-viewer.showCacheStatistics",
260+
"when": "view == logFiles && magentoLogViewer.hasMagentoRoot",
261+
"group": "navigation@5"
262+
},
231263
{
232264
"command": "magento-log-viewer.refreshReportFiles",
233265
"when": "view == reportFiles && magentoLogViewer.hasMagentoRoot",

src/helpers.ts

Lines changed: 93 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,14 @@ export function registerCommands(context: vscode.ExtensionContext, logViewerProv
100100

101101
// Search commands
102102
vscode.commands.registerCommand('magento-log-viewer.searchLogs', () => logViewerProvider.searchInLogs());
103-
vscode.commands.registerCommand('magento-log-viewer.clearSearch', () => logViewerProvider.clearSearch()); // Improved command registration for openFile
103+
vscode.commands.registerCommand('magento-log-viewer.clearSearch', () => logViewerProvider.clearSearch());
104+
105+
// Cache management commands
106+
vscode.commands.registerCommand('magento-log-viewer.showCacheStatistics', () => {
107+
const stats = getCacheStatistics();
108+
const message = `Cache: ${stats.size}/${stats.maxSize} files | Memory: ${stats.memoryUsage} | Max file size: ${Math.round(stats.maxFileSize / 1024 / 1024)} MB`;
109+
vscode.window.showInformationMessage(message);
110+
}); // Improved command registration for openFile
104111
vscode.commands.registerCommand('magento-log-viewer.openFile', (filePath: string | unknown, lineNumber?: number) => {
105112
// If filePath is not a string, show a selection box with available log files
106113
if (typeof filePath !== 'string') {
@@ -429,8 +436,39 @@ const reportCache = new Map<string, { content: unknown, timestamp: number }>();
429436

430437
// Cache for file contents to avoid repeated reads
431438
const fileContentCache = new Map<string, { content: string, timestamp: number }>();
432-
const FILE_CACHE_MAX_SIZE = 50; // Maximum number of files to cache
433-
const FILE_CACHE_MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB max file size for caching
439+
440+
// Dynamic cache configuration based on available memory and user settings
441+
const getCacheConfig = () => {
442+
// Get user configuration
443+
const workspaceUri = vscode.workspace.workspaceFolders?.[0]?.uri || null;
444+
const config = vscode.workspace.getConfiguration('magentoLogViewer', workspaceUri);
445+
446+
const userMaxFiles = config.get<number>('cacheMaxFiles', 0);
447+
const userMaxFileSize = config.get<number>('cacheMaxFileSize', 0);
448+
449+
// If user has set specific values, use them
450+
if (userMaxFiles > 0 && userMaxFileSize > 0) {
451+
return {
452+
maxSize: userMaxFiles,
453+
maxFileSize: userMaxFileSize * 1024 * 1024 // Convert MB to bytes
454+
};
455+
}
456+
457+
// Otherwise use automatic calculation
458+
const totalMemory = process.memoryUsage().heapTotal;
459+
const availableMemory = totalMemory - process.memoryUsage().heapUsed;
460+
461+
// Use up to 10% of available heap memory for caching
462+
const maxCacheMemory = Math.min(availableMemory * 0.1, 50 * 1024 * 1024); // Max 50MB
463+
464+
const autoMaxSize = userMaxFiles > 0 ? userMaxFiles : Math.max(20, Math.min(100, Math.floor(maxCacheMemory / (2 * 1024 * 1024))));
465+
const autoMaxFileSize = userMaxFileSize > 0 ? userMaxFileSize * 1024 * 1024 : Math.max(1024 * 1024, Math.min(10 * 1024 * 1024, maxCacheMemory / 10));
466+
467+
return {
468+
maxSize: autoMaxSize,
469+
maxFileSize: autoMaxFileSize
470+
};
471+
};const CACHE_CONFIG = getCacheConfig();
434472

435473
// Helper function for reading and parsing JSON reports with caching
436474
function getReportContent(filePath: string): unknown | null {
@@ -470,8 +508,8 @@ export function getCachedFileContent(filePath: string): string | null {
470508

471509
const stats = fs.statSync(filePath);
472510

473-
// Don't cache files larger than 5MB to prevent memory issues
474-
if (stats.size > FILE_CACHE_MAX_FILE_SIZE) {
511+
// Don't cache files larger than configured limit to prevent memory issues
512+
if (stats.size > CACHE_CONFIG.maxFileSize) {
475513
return fs.readFileSync(filePath, 'utf-8');
476514
}
477515

@@ -486,10 +524,13 @@ export function getCachedFileContent(filePath: string): string | null {
486524
const content = fs.readFileSync(filePath, 'utf-8');
487525

488526
// Manage cache size - remove oldest entries if cache is full
489-
if (fileContentCache.size >= FILE_CACHE_MAX_SIZE) {
490-
const oldestKey = fileContentCache.keys().next().value;
491-
if (oldestKey) {
492-
fileContentCache.delete(oldestKey);
527+
if (fileContentCache.size >= CACHE_CONFIG.maxSize) {
528+
// Remove multiple old entries if we're significantly over the limit
529+
const entriesToRemove = Math.max(1, Math.floor(CACHE_CONFIG.maxSize * 0.1));
530+
const keys = Array.from(fileContentCache.keys());
531+
532+
for (let i = 0; i < entriesToRemove && keys.length > 0; i++) {
533+
fileContentCache.delete(keys[i]);
493534
}
494535
}
495536

@@ -511,13 +552,55 @@ export function clearFileContentCache(): void {
511552
fileContentCache.clear();
512553
}
513554

514-
// Function to invalidate cache for a specific file
555+
// Function to get cache statistics for monitoring
556+
export function getCacheStatistics(): { size: number; maxSize: number; maxFileSize: number; memoryUsage: string } {
557+
const currentConfig = getCacheConfig();
558+
const memoryUsed = Array.from(fileContentCache.values())
559+
.reduce((total, item) => total + (item.content.length * 2), 0); // Rough estimate (UTF-16)
560+
561+
const stats = {
562+
size: fileContentCache.size,
563+
maxSize: currentConfig.maxSize,
564+
maxFileSize: currentConfig.maxFileSize,
565+
memoryUsage: `${Math.round(memoryUsed / 1024 / 1024 * 100) / 100} MB`
566+
};
567+
568+
// Log statistics if enabled in settings
569+
const workspaceUri = vscode.workspace.workspaceFolders?.[0]?.uri || null;
570+
const config = vscode.workspace.getConfiguration('magentoLogViewer', workspaceUri);
571+
const enableLogging = config.get<boolean>('enableCacheStatistics', false);
572+
573+
if (enableLogging) {
574+
console.log('Magento Log Viewer Cache Statistics:', stats);
575+
}
576+
577+
return stats;
578+
}// Function to invalidate cache for a specific file
515579
export function invalidateFileCache(filePath: string): void {
516580
fileContentCache.delete(filePath);
517581
reportCache.delete(filePath);
518582
lineCountCache.delete(filePath);
519583
}
520584

585+
// Function to optimize cache size based on current memory pressure
586+
export function optimizeCacheSize(): void {
587+
const memoryUsage = process.memoryUsage();
588+
const heapUsedRatio = memoryUsage.heapUsed / memoryUsage.heapTotal;
589+
590+
// If memory usage is high (>80%), aggressively clean cache
591+
if (heapUsedRatio > 0.8) {
592+
const targetSize = Math.floor(fileContentCache.size * 0.5);
593+
const keys = Array.from(fileContentCache.keys());
594+
const entriesToRemove = fileContentCache.size - targetSize;
595+
596+
for (let i = 0; i < entriesToRemove && keys.length > 0; i++) {
597+
fileContentCache.delete(keys[i]);
598+
}
599+
600+
console.log(`Cache optimized: Removed ${entriesToRemove} entries due to memory pressure`);
601+
}
602+
}
603+
521604
export function parseReportTitle(filePath: string): string {
522605
try {
523606
const report = getReportContent(filePath);

0 commit comments

Comments
 (0)