mirror of
https://github.com/Grace-Solutions/PSMinIO.git
synced 2026-08-30 13:49:08 +00:00
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:
Binary file not shown.
Binary file not shown.
@@ -19,10 +19,10 @@ namespace PSMinIO.Utils
|
|||||||
private bool _disposed = false;
|
private bool _disposed = false;
|
||||||
|
|
||||||
// Performance optimization fields
|
// 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 long _bytesWrittenSinceFlush = 0;
|
||||||
private DateTime _lastFlush = DateTime.UtcNow;
|
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
|
// Cancellation support
|
||||||
private CancellationTokenSource? _cancellationTokenSource;
|
private CancellationTokenSource? _cancellationTokenSource;
|
||||||
@@ -110,12 +110,12 @@ namespace PSMinIO.Utils
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_archive?.Dispose(); // This forces the zip to be finalized
|
// Force flush the output stream first
|
||||||
_outputStream?.Flush();
|
_outputStream?.Flush();
|
||||||
|
|
||||||
if (_outputStream is FileStream fileStream)
|
if (_outputStream is FileStream fileStream)
|
||||||
{
|
{
|
||||||
fileStream.Flush(true); // Force OS flush
|
fileStream.Flush(true); // Force OS flush to disk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
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>
|
/// <summary>
|
||||||
/// Gets optimal buffer size based on file size
|
/// Gets optimal buffer size based on file size
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -249,7 +287,7 @@ namespace PSMinIO.Utils
|
|||||||
(now - _lastFlush).TotalMilliseconds > FlushIntervalMs)
|
(now - _lastFlush).TotalMilliseconds > FlushIntervalMs)
|
||||||
{
|
{
|
||||||
entryStream.Flush();
|
entryStream.Flush();
|
||||||
_outputStream.Flush(); // Also flush the underlying stream
|
AggressiveFlush(); // Force all data to disk immediately
|
||||||
_bytesWrittenSinceFlush = 0;
|
_bytesWrittenSinceFlush = 0;
|
||||||
_lastFlush = now;
|
_lastFlush = now;
|
||||||
}
|
}
|
||||||
@@ -269,7 +307,7 @@ namespace PSMinIO.Utils
|
|||||||
|
|
||||||
// Final flush for this file
|
// Final flush for this file
|
||||||
entryStream.Flush();
|
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)
|
// Update metrics (access CompressedLength after the entry stream is closed)
|
||||||
|
|||||||
@@ -204,12 +204,18 @@ namespace PSMinIO.Utils
|
|||||||
/// <returns>Zip creation result</returns>
|
/// <returns>Zip creation result</returns>
|
||||||
public ZipCreationResult CreateResult(string zipFilePath)
|
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
|
return new ZipCreationResult
|
||||||
{
|
{
|
||||||
ZipFilePath = zipFilePath,
|
ZipFilePath = zipFilePath,
|
||||||
StartTime = _zipBuilder.StartTime,
|
StartTime = _zipBuilder.StartTime,
|
||||||
EndTime = _zipBuilder.EndTime ?? DateTime.UtcNow,
|
EndTime = endTime,
|
||||||
Duration = _zipBuilder.Duration ?? TimeSpan.Zero,
|
Duration = duration,
|
||||||
FileCount = _zipBuilder.FileCount,
|
FileCount = _zipBuilder.FileCount,
|
||||||
TotalUncompressedSize = _zipBuilder.TotalUncompressedSize,
|
TotalUncompressedSize = _zipBuilder.TotalUncompressedSize,
|
||||||
TotalCompressedSize = _zipBuilder.TotalCompressedSize,
|
TotalCompressedSize = _zipBuilder.TotalCompressedSize,
|
||||||
|
|||||||
Reference in New Issue
Block a user