tests/Performance/Measure-MemoryProfile.ps1

<#
.SYNOPSIS
    Profiles memory usage and detects memory leaks.
 
.DESCRIPTION
    Executes operations repeatedly to detect memory leaks and analyze memory consumption patterns.
 
.EXAMPLE
    .\Measure-MemoryProfile.ps1
#>


[CmdletBinding()]
param()

# Import HermesConsoleUI module
$modulePath = Join-Path $PSScriptRoot "..\..\HermesConsoleUI.psm1"
Import-Module $modulePath -Force

function Get-MemoryUsage {
    $process = Get-Process -Id $PID
    [Math]::Round($process.WorkingSet64 / 1MB, 2)
}

function Test-MemoryLeak {
    param(
        [scriptblock]$Operation,
        [string]$OperationName,
        [int]$Iterations = 1000
    )
    
    Write-Host "`nTesting: $OperationName" -ForegroundColor Yellow
    
    $memorySnapshots = @()
    $sampleInterval = [Math]::Max(1, $Iterations / 20) # Take 20 samples
    
    for ($i = 0; $i -lt $Iterations; $i++) {
        & $Operation
        
        if ($i % $sampleInterval -eq 0) {
            $memorySnapshots += [PSCustomObject]@{
                Iteration = $i
                MemoryMB  = Get-MemoryUsage
            }
        }
    }
    
    # Force garbage collection
    [GC]::Collect()
    [GC]::WaitForPendingFinalizers()
    [GC]::Collect()
    Start-Sleep -Milliseconds 500
    
    $memoryAfterGC = Get-MemoryUsage
    
    # Analyze trend
    $firstMemory = $memorySnapshots[0].MemoryMB
    $lastMemory = $memorySnapshots[-1].MemoryMB
    $memoryGrowth = $lastMemory - $firstMemory
    $memoryAfterGCDelta = $memoryAfterGC - $firstMemory
    
    $leakDetected = $memoryAfterGCDelta -gt 5 # More than 5MB growth after GC
    
    [PSCustomObject]@{
        OperationName        = $OperationName
        Iterations           = $Iterations
        InitialMemoryMB      = $firstMemory
        FinalMemoryMB        = $lastMemory
        MemoryGrowthMB       = [Math]::Round($memoryGrowth, 2)
        MemoryAfterGCMB      = $memoryAfterGC
        MemoryAfterGCDeltaMB = [Math]::Round($memoryAfterGCDelta, 2)
        LeakDetected         = $leakDetected
        Snapshots            = $memorySnapshots
    }
}

Write-Host "`n=== Memory Profiling ===" -ForegroundColor Cyan
Write-Host "Running memory leak detection tests...`n"

$results = @()

# Test 1: Table rendering
$results += Test-MemoryLeak -OperationName "Table Rendering (100 rows)" -Operation {
    $data = 1..100 | ForEach-Object {
        [PSCustomObject]@{ ID = $_; Name = "Item $_"; Value = $_ * 10 }
    }
    $null = $data | Format-Table | Out-String
}

# Test 2: String manipulation
$results += Test-MemoryLeak -OperationName "String Colorization" -Operation {
    $text = "This is a test string with multiple words"
    $null = $text -replace '(\w+)', "`e[32m`$1`e[0m"
}

# Test 3: Array operations
$results += Test-MemoryLeak -OperationName "Array Building" -Operation {
    $arr = @()
    for ($i = 0; $i -lt 50; $i++) {
        $arr += "Item $i"
    }
    $null = $arr
}

# Display results
Write-Host "`n=== Memory Leak Detection Results ===" -ForegroundColor Cyan
$results | Select-Object OperationName, Iterations, InitialMemoryMB, FinalMemoryMB, MemoryGrowthMB, MemoryAfterGCDeltaMB, LeakDetected | Format-Table -AutoSize

# Summary
$leaksFound = ($results | Where-Object { $_.LeakDetected }).Count
if ($leaksFound -gt 0) {
    Write-Host "`n⚠️ WARNING: $leaksFound potential memory leak(s) detected!" -ForegroundColor Red
}
else {
    Write-Host "`n✅ No memory leaks detected" -ForegroundColor Green
}

# Export results
$outputPath = Join-Path $PSScriptRoot "memory_profile_results.json"
$results | Select-Object -Property * -ExcludeProperty Snapshots | ConvertTo-Json -Depth 3 | Out-File $outputPath
Write-Host "`nResults exported to: $outputPath" -ForegroundColor Yellow

return $results