using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using AdvChkSys.Diagnostics; namespace ChunkMark { /// /// Provides detailed memory reporting and visualization for benchmarks. /// public class MemoryReporter { private readonly List _snapshots = new List(); private readonly Stopwatch _timer = new Stopwatch(); private readonly string _reportName; public MemoryReporter(string reportName) { _reportName = reportName; _timer.Start(); } /// /// Takes a memory snapshot with the given label. /// public void TakeSnapshot(string label) { var report = AdvChkSys.AdvChkSys.GetMemoryUsage(); _snapshots.Add(new MemorySnapshot { Label = label, TimeSeconds = _timer.Elapsed.TotalSeconds, Report = report }); } /// /// Generates a detailed memory report as a string. /// public string GenerateReport() { if (_snapshots.Count == 0) return "No memory snapshots recorded."; var sb = new StringBuilder(); sb.AppendLine($"Memory Report: {_reportName}"); sb.AppendLine("=".PadRight(50, '=')); sb.AppendLine(); sb.AppendLine("Snapshots:"); sb.AppendLine("┌─────────────────┬──────────┬─────────────────┬─────────────┬───────────┐"); sb.AppendLine("│ Label │ Time (s) │ Chunk Memory │ Active │ Usage % │"); sb.AppendLine("├─────────────────┼──────────┼─────────────────┼─────────────┼───────────┤"); foreach (var snapshot in _snapshots) { string label = snapshot.Label.PadRight(15).Substring(0, 15); string time = $"{snapshot.TimeSeconds:F2}".PadRight(8).Substring(0, 8); string memory = FormatByteSize(snapshot.Report.EstimatedChunkMemoryBytes).PadRight(15).Substring(0, 15); string active = $"{snapshot.Report.ActiveChunkCount:N0}".PadRight(11).Substring(0, 11); string usage = $"{snapshot.Report.MemoryUsagePercentage:F2}%".PadRight(9).Substring(0, 9); sb.AppendLine($"│ {label} │ {time} │ {memory} │ {active} │ {usage} │"); } sb.AppendLine("└─────────────────┴──────────┴─────────────────┴─────────────┴───────────┘"); sb.AppendLine(); // Memory change analysis if (_snapshots.Count >= 2) { var first = _snapshots.First(); var last = _snapshots.Last(); var maxMem = _snapshots.Max(s => s.Report.EstimatedChunkMemoryBytes); var minMem = _snapshots.Min(s => s.Report.EstimatedChunkMemoryBytes); sb.AppendLine("Memory Analysis:"); sb.AppendLine($" Initial Memory: {FormatByteSize(first.Report.EstimatedChunkMemoryBytes)}"); sb.AppendLine($" Final Memory: {FormatByteSize(last.Report.EstimatedChunkMemoryBytes)}"); sb.AppendLine($" Net Change: {FormatByteSize(last.Report.EstimatedChunkMemoryBytes - first.Report.EstimatedChunkMemoryBytes)}"); sb.AppendLine($" Peak Memory: {FormatByteSize(maxMem)}"); sb.AppendLine($" Minimum Memory: {FormatByteSize(minMem)}"); sb.AppendLine($" Memory Volatility: {FormatByteSize(maxMem - minMem)}"); } return sb.ToString(); } /// /// Saves the memory report to a file. /// public void SaveReportToFile(string filePath) { string report = GenerateReport(); File.WriteAllText(filePath, report); } /// /// Formats a byte size into a human-readable string (KB, MB, GB). /// private static string FormatByteSize(ulong bytes) { string[] sizes = { "B", "KB", "MB", "GB", "TB" }; double formattedSize = bytes; int order = 0; while (formattedSize >= 1024 && order < sizes.Length - 1) { order++; formattedSize /= 1024; } return $"{formattedSize:F2} {sizes[order]}"; } private class MemorySnapshot { public string Label { get; set; } = ""; public double TimeSeconds { get; set; } public MemoryUsageReport Report { get; set; } = null!; } } }