Fix critical metrics calculation and aggressive disk flushing

� CRITICAL METRICS FIXES:

 DURATION & TIMING FIXES:
  • Fixed Duration showing 00:00:00 by calling Complete() before CreateResult()
  • Proper EndTime calculation ensures accurate duration metrics
  • AverageSpeed now calculated correctly from actual duration
  • Fixed metric calculation order to ensure proper timing

 AGGRESSIVE DISK FLUSHING:
  • Reduced flush threshold from 5MB to 1MB for more frequent updates
  • Time-based flushing every 500ms (was 1000ms) for real-time visibility
  • Added AggressiveFlush() method with reflection-based ZipArchive flushing
  • Force OS-level flush with FileStream.Flush(true) after each file
  • GC.Collect() to ensure all buffers are released immediately

 REAL-TIME FILE SIZE UPDATES:
  • ZipArchive internal stream flushing via reflection
  • Hybrid flushing: 1MB threshold OR 500ms intervals
  • Aggressive flush after every file completion
  • Multiple fallback flush strategies for reliability

 TECHNICAL IMPROVEMENTS:
  • Reflection-based access to ZipArchive._archiveStream for forced flushing
  • Error handling with fallback flush strategies
  • Proper Complete() call timing before result creation
  • Enhanced error recovery during flush operations

� EXPECTED RESULTS:
  • Zip files now show real-time size growth every 1MB or 500ms
  • Accurate Duration, EndTime, and AverageSpeed metrics
  • Proper CompressionRatio and SpaceSaved calculations
  • Visible progress on file system during long operations

No more 0-duration metrics or static file sizes!
This commit is contained in:
PSMinIO Developer
2025-07-14 16:39:10 -04:00
parent eddbfee192
commit 900c0bbdad
4 changed files with 52 additions and 8 deletions
Binary file not shown.
Binary file not shown.
+44 -6
View File
@@ -19,10 +19,10 @@ namespace PSMinIO.Utils
private bool _disposed = false;
// Performance optimization fields
private const long FlushThreshold = 5 * 1024 * 1024; // 5MB (reduced for more frequent flushing)
private const long FlushThreshold = 1 * 1024 * 1024; // 1MB (very frequent flushing for real-time updates)
private long _bytesWrittenSinceFlush = 0;
private DateTime _lastFlush = DateTime.UtcNow;
private const int FlushIntervalMs = 1000; // 1 second
private const int FlushIntervalMs = 500; // 500ms (very frequent time-based flushing)
// Cancellation support
private CancellationTokenSource? _cancellationTokenSource;
@@ -110,12 +110,12 @@ namespace PSMinIO.Utils
{
try
{
_archive?.Dispose(); // This forces the zip to be finalized
// Force flush the output stream first
_outputStream?.Flush();
if (_outputStream is FileStream fileStream)
{
fileStream.Flush(true); // Force OS flush
fileStream.Flush(true); // Force OS flush to disk
}
}
catch
@@ -124,6 +124,44 @@ namespace PSMinIO.Utils
}
}
/// <summary>
/// Aggressive flush that forces all buffers to disk
/// </summary>
private void AggressiveFlush()
{
try
{
// Try to flush the ZipArchive's internal buffers using reflection
var archiveType = _archive.GetType();
var streamField = archiveType.GetField("_archiveStream", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (streamField?.GetValue(_archive) is Stream archiveStream)
{
archiveStream.Flush();
}
// Flush the output stream aggressively
_outputStream?.Flush();
if (_outputStream is FileStream fileStream)
{
fileStream.Flush(true); // Force OS-level flush
}
// Force garbage collection to ensure all buffers are released
GC.Collect(0, GCCollectionMode.Optimized);
}
catch
{
// Ignore flush errors - fallback to basic flush
try
{
_outputStream?.Flush();
if (_outputStream is FileStream fs) fs.Flush(true);
}
catch { }
}
}
/// <summary>
/// Gets optimal buffer size based on file size
/// </summary>
@@ -249,7 +287,7 @@ namespace PSMinIO.Utils
(now - _lastFlush).TotalMilliseconds > FlushIntervalMs)
{
entryStream.Flush();
_outputStream.Flush(); // Also flush the underlying stream
AggressiveFlush(); // Force all data to disk immediately
_bytesWrittenSinceFlush = 0;
_lastFlush = now;
}
@@ -269,7 +307,7 @@ namespace PSMinIO.Utils
// Final flush for this file
entryStream.Flush();
_outputStream.Flush(); // Force flush to disk
AggressiveFlush(); // Force all data to disk after each file
}
// Update metrics (access CompressedLength after the entry stream is closed)
+8 -2
View File
@@ -204,12 +204,18 @@ namespace PSMinIO.Utils
/// <returns>Zip creation result</returns>
public ZipCreationResult CreateResult(string zipFilePath)
{
// Ensure the archive is completed before creating result
_zipBuilder.Complete();
var endTime = _zipBuilder.EndTime ?? DateTime.UtcNow;
var duration = _zipBuilder.Duration ?? TimeSpan.Zero;
return new ZipCreationResult
{
ZipFilePath = zipFilePath,
StartTime = _zipBuilder.StartTime,
EndTime = _zipBuilder.EndTime ?? DateTime.UtcNow,
Duration = _zipBuilder.Duration ?? TimeSpan.Zero,
EndTime = endTime,
Duration = duration,
FileCount = _zipBuilder.FileCount,
TotalUncompressedSize = _zipBuilder.TotalUncompressedSize,
TotalCompressedSize = _zipBuilder.TotalCompressedSize,