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!;
}
}
}