@@ -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
431438const 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
436474function 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
515579export 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+
521604export function parseReportTitle ( filePath : string ) : string {
522605 try {
523606 const report = getReportContent ( filePath ) ;
0 commit comments