1
0
mirror of https://github.com/tw93/Mole.git synced 2026-02-04 15:39:42 +00:00

perf(windows): speed up analyze scanning with shallow depth

- Reduce timeout from 5s to 500ms per directory
- Limit scan depth to 3 levels for quick size estimation
- Reduce max files scanned from 50k to 10k
- Results now appear in 1-2 seconds instead of minutes
This commit is contained in:
Bhadra
2026-01-08 19:40:38 +05:30
parent 3653900e2d
commit 7b03fceaf8

View File

@@ -20,9 +20,10 @@ import (
// Scanning limits to prevent infinite scanning // Scanning limits to prevent infinite scanning
const ( const (
dirSizeTimeout = 5 * time.Second // Max time to calculate a single directory size dirSizeTimeout = 500 * time.Millisecond // Max time to calculate a single directory size
maxFilesPerDir = 50000 // Max files to scan per directory maxFilesPerDir = 10000 // Max files to scan per directory
maxScanDepth = 50 // Max recursion depth maxScanDepth = 10 // Max recursion depth (shallow scan)
shallowScanDepth = 3 // Depth for quick size estimation
) )
// ANSI color codes // ANSI color codes
@@ -564,6 +565,7 @@ func scanDirectory(path string) ([]dirEntry, []fileEntry, int64, error) {
} }
// calculateDirSize calculates the size of a directory with timeout and limits // calculateDirSize calculates the size of a directory with timeout and limits
// Uses shallow scanning for speed - estimates based on first few levels
func calculateDirSize(path string) int64 { func calculateDirSize(path string) int64 {
ctx, cancel := context.WithTimeout(context.Background(), dirSizeTimeout) ctx, cancel := context.WithTimeout(context.Background(), dirSizeTimeout)
defer cancel() defer cancel()
@@ -576,21 +578,21 @@ func calculateDirSize(path string) int64 {
go func() { go func() {
defer close(done) defer close(done)
walkDirWithLimit(ctx, path, 0, &size, &fileCount) quickScanDir(ctx, path, 0, &size, &fileCount)
}() }()
select { select {
case <-done: case <-done:
// Completed normally // Completed normally
case <-ctx.Done(): case <-ctx.Done():
// Timeout - return partial size // Timeout - return partial size (already accumulated)
} }
return size return size
} }
// walkDirWithLimit walks a directory with depth limit and file count limit // quickScanDir does a fast shallow scan for size estimation
func walkDirWithLimit(ctx context.Context, path string, depth int, size *int64, fileCount *int64) { func quickScanDir(ctx context.Context, path string, depth int, size *int64, fileCount *int64) {
// Check context cancellation // Check context cancellation
select { select {
case <-ctx.Done(): case <-ctx.Done():
@@ -598,12 +600,12 @@ func walkDirWithLimit(ctx context.Context, path string, depth int, size *int64,
default: default:
} }
// Check depth limit // Limit depth for speed
if depth > maxScanDepth { if depth > shallowScanDepth {
return return
} }
// Check file count limit // Limit total files scanned
if atomic.LoadInt64(fileCount) > maxFilesPerDir { if atomic.LoadInt64(fileCount) > maxFilesPerDir {
return return
} }
@@ -614,14 +616,13 @@ func walkDirWithLimit(ctx context.Context, path string, depth int, size *int64,
} }
for _, entry := range entries { for _, entry := range entries {
// Check cancellation frequently // Check cancellation
select { select {
case <-ctx.Done(): case <-ctx.Done():
return return
default: default:
} }
// Check file count limit
if atomic.LoadInt64(fileCount) > maxFilesPerDir { if atomic.LoadInt64(fileCount) > maxFilesPerDir {
return return
} }
@@ -629,12 +630,12 @@ func walkDirWithLimit(ctx context.Context, path string, depth int, size *int64,
entryPath := filepath.Join(path, entry.Name()) entryPath := filepath.Join(path, entry.Name())
if entry.IsDir() { if entry.IsDir() {
// Skip system/protected directories
name := entry.Name() name := entry.Name()
if skipPatterns[name] || strings.HasPrefix(name, ".") && len(name) > 1 { // Skip hidden and system directories
if skipPatterns[name] || (strings.HasPrefix(name, ".") && len(name) > 1) {
continue continue
} }
walkDirWithLimit(ctx, entryPath, depth+1, size, fileCount) quickScanDir(ctx, entryPath, depth+1, size, fileCount)
} else { } else {
info, err := entry.Info() info, err := entry.Info()
if err == nil { if err == nil {