[Media scan] Change speed calculation algorithm for one more stable and with less spikes.

This commit is contained in:
2025-11-20 03:45:32 +00:00
parent c540bd794d
commit e201ebcf9d
3 changed files with 99 additions and 90 deletions

View File

@@ -126,10 +126,9 @@ public sealed partial class MediaScan
mhddLog = new MhddLog(_mhddLogPath, _dev, results.Blocks, blockSize, blocksToRead, false); mhddLog = new MhddLog(_mhddLogPath, _dev, results.Blocks, blockSize, blocksToRead, false);
ibgLog = new IbgLog(_ibgLogPath, ataProfile); ibgLog = new IbgLog(_ibgLogPath, ataProfile);
_scanStopwatch.Restart();
_speedStopwatch.Restart();
ulong sectorSpeedStart = 0;
InitProgress?.Invoke(); InitProgress?.Invoke();
uint accumulatedSpeedSectors = 0;
double accumulatedSpeedMs = 0;
for(ulong i = 0; i < results.Blocks; i += blocksToRead) for(ulong i = 0; i < results.Blocks; i += blocksToRead)
{ {
@@ -150,7 +149,11 @@ public sealed partial class MediaScan
(long)i, (long)i,
(long)results.Blocks); (long)results.Blocks);
_speedStopwatch.Restart();
bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration, out _, out _); bool error = ataReader.ReadBlocks(out cmdBuf, i, blocksToRead, out duration, out _, out _);
_speedStopwatch.Stop();
accumulatedSpeedMs += _speedStopwatch.ElapsedMilliseconds;
accumulatedSpeedSectors += blocksToRead;
if(!error) if(!error)
{ {
@@ -198,16 +201,13 @@ public sealed partial class MediaScan
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
} }
sectorSpeedStart += blocksToRead; if(accumulatedSpeedMs >= 100)
{
double elapsed = _speedStopwatch.Elapsed.TotalSeconds; currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0));
if(elapsed <= 0) continue;
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
ScanSpeed?.Invoke(i, currentSpeed * 1024); ScanSpeed?.Invoke(i, currentSpeed * 1024);
sectorSpeedStart = 0; accumulatedSpeedMs = 0;
_speedStopwatch.Restart(); accumulatedSpeedSectors = 0;
}
} }
_speedStopwatch.Stop(); _speedStopwatch.Stop();
@@ -215,6 +215,8 @@ public sealed partial class MediaScan
EndProgress?.Invoke(); EndProgress?.Invoke();
mhddLog.Close(); mhddLog.Close();
currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0));
ibgLog.Close(_dev, ibgLog.Close(_dev,
results.Blocks, results.Blocks,
blockSize, blockSize,
@@ -227,11 +229,11 @@ public sealed partial class MediaScan
if(ataReader.CanSeekLba && _seekTest) if(ataReader.CanSeekLba && _seekTest)
{ {
for(int i = 0; i < seekTimes; i++) for(var i = 0; i < seekTimes; i++)
{ {
if(_aborted) break; if(_aborted) break;
uint seekPos = (uint)rnd.Next((int)results.Blocks); var seekPos = (uint)rnd.Next((int)results.Blocks);
PulseProgress?.Invoke(string.Format(Localization.Core.Seeking_to_sector_0, seekPos)); PulseProgress?.Invoke(string.Format(Localization.Core.Seeking_to_sector_0, seekPos));
@@ -256,10 +258,9 @@ public sealed partial class MediaScan
ulong currentBlock = 0; ulong currentBlock = 0;
results.Blocks = (ulong)(cylinders * heads * sectors); results.Blocks = (ulong)(cylinders * heads * sectors);
_scanStopwatch.Restart();
_speedStopwatch.Restart();
ulong sectorSpeedStart = 0;
InitProgress?.Invoke(); InitProgress?.Invoke();
uint accumulatedSpeedSectors = 0;
double accumulatedSpeedMs = 0;
for(ushort cy = 0; cy < cylinders; cy++) for(ushort cy = 0; cy < cylinders; cy++)
{ {
@@ -281,7 +282,10 @@ public sealed partial class MediaScan
.Per(_oneSecond) .Per(_oneSecond)
.Humanize())); .Humanize()));
_speedStopwatch.Restart();
bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration, out _); bool error = ataReader.ReadChs(out cmdBuf, cy, hd, sc, out duration, out _);
accumulatedSpeedMs += _speedStopwatch.ElapsedMilliseconds;
accumulatedSpeedSectors++;
if(!error) if(!error)
{ {
@@ -320,24 +324,23 @@ public sealed partial class MediaScan
else else
{ {
ScanUnreadable?.Invoke(currentBlock); ScanUnreadable?.Invoke(currentBlock);
results.Errored += blocksToRead; results.Errored++;
results.UnreadableSectors.Add(currentBlock); results.UnreadableSectors.Add(currentBlock);
mhddLog.Write(currentBlock, duration < 500 ? 65535 : duration); mhddLog.Write(currentBlock, duration < 500 ? 65535 : duration);
ibgLog.Write(currentBlock, 0); ibgLog.Write(currentBlock, 0);
} }
sectorSpeedStart++; if(accumulatedSpeedMs >= 100)
currentBlock++; {
currentSpeed = accumulatedSpeedSectors *
blockSize /
(1048576 * (accumulatedSpeedMs / 1000.0));
double elapsed = _speedStopwatch.Elapsed.TotalSeconds;
if(elapsed <= 0) continue;
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
ScanSpeed?.Invoke(currentBlock, currentSpeed * 1024); ScanSpeed?.Invoke(currentBlock, currentSpeed * 1024);
sectorSpeedStart = 0; accumulatedSpeedMs = 0;
_speedStopwatch.Restart(); accumulatedSpeedSectors = 0;
}
} }
} }
} }
@@ -347,6 +350,8 @@ public sealed partial class MediaScan
EndProgress?.Invoke(); EndProgress?.Invoke();
mhddLog.Close(); mhddLog.Close();
currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0));
ibgLog.Close(_dev, ibgLog.Close(_dev,
results.Blocks, results.Blocks,
blockSize, blockSize,
@@ -359,13 +364,13 @@ public sealed partial class MediaScan
if(ataReader.CanSeek) if(ataReader.CanSeek)
{ {
for(int i = 0; i < seekTimes; i++) for(var i = 0; i < seekTimes; i++)
{ {
if(_aborted) break; if(_aborted) break;
ushort seekCy = (ushort)rnd.Next(cylinders); var seekCy = (ushort)rnd.Next(cylinders);
byte seekHd = (byte)rnd.Next(heads); var seekHd = (byte)rnd.Next(heads);
byte seekSc = (byte)rnd.Next(sectors); var seekSc = (byte)rnd.Next(sectors);
PulseProgress?.Invoke(string.Format(Localization.Core.Seeking_to_cylinder_0_head_1_sector_2, PulseProgress?.Invoke(string.Format(Localization.Core.Seeking_to_cylinder_0_head_1_sector_2,
seekCy, seekCy,

View File

@@ -56,8 +56,8 @@ public sealed partial class MediaScan
bool sense; bool sense;
uint blockSize = 0; uint blockSize = 0;
ushort currentProfile = 0x0001; ushort currentProfile = 0x0001;
bool foundReadCommand = false; var foundReadCommand = false;
bool readcd = false; var readcd = false;
results.Blocks = 0; results.Blocks = 0;
@@ -76,7 +76,7 @@ public sealed partial class MediaScan
{ {
case 0x3A: case 0x3A:
{ {
int leftRetries = 5; var leftRetries = 5;
while(leftRetries > 0) while(leftRetries > 0)
{ {
@@ -101,7 +101,7 @@ public sealed partial class MediaScan
} }
case 0x04 when decSense.Value.ASCQ == 0x01: case 0x04 when decSense.Value.ASCQ == 0x01:
{ {
int leftRetries = 10; var leftRetries = 10;
while(leftRetries > 0) while(leftRetries > 0)
{ {
@@ -130,7 +130,7 @@ public sealed partial class MediaScan
// These should be trapped by the OS but seems in some cases they're not // These should be trapped by the OS but seems in some cases they're not
case 0x28: case 0x28:
{ {
int leftRetries = 10; var leftRetries = 10;
while(leftRetries > 0) while(leftRetries > 0)
{ {
@@ -222,7 +222,7 @@ public sealed partial class MediaScan
return results; return results;
} }
bool compactDisc = true; var compactDisc = true;
FullTOC.CDFullTOC? toc = null; FullTOC.CDFullTOC? toc = null;
if(_dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice) if(_dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice)
@@ -368,10 +368,10 @@ public sealed partial class MediaScan
InitBlockMap?.Invoke(results.Blocks, blockSize, blocksToRead, currentProfile); InitBlockMap?.Invoke(results.Blocks, blockSize, blocksToRead, currentProfile);
mhddLog = new MhddLog(_mhddLogPath, _dev, results.Blocks, blockSize, blocksToRead, false); mhddLog = new MhddLog(_mhddLogPath, _dev, results.Blocks, blockSize, blocksToRead, false);
ibgLog = new IbgLog(_ibgLogPath, currentProfile); ibgLog = new IbgLog(_ibgLogPath, currentProfile);
_speedStopwatch.Restart();
ulong sectorSpeedStart = 0;
InitProgress?.Invoke(); InitProgress?.Invoke();
uint accumulatedSpeedSectors = 0;
double accumulatedSpeedMs = 0;
for(ulong i = 0; i < results.Blocks; i += blocksToRead) for(ulong i = 0; i < results.Blocks; i += blocksToRead)
{ {
@@ -392,6 +392,8 @@ public sealed partial class MediaScan
(long)i, (long)i,
(long)results.Blocks); (long)results.Blocks);
_speedStopwatch.Restart();
if(readcd) if(readcd)
{ {
sense = _dev.ReadCd(out _, sense = _dev.ReadCd(out _,
@@ -414,6 +416,10 @@ public sealed partial class MediaScan
else else
sense = scsiReader.ReadBlocks(out _, i, blocksToRead, out cmdDuration, out _, out _); sense = scsiReader.ReadBlocks(out _, i, blocksToRead, out cmdDuration, out _, out _);
_speedStopwatch.Stop();
accumulatedSpeedMs += _speedStopwatch.ElapsedMilliseconds;
accumulatedSpeedSectors += blocksToRead;
results.ProcessingTime += cmdDuration; results.ProcessingTime += cmdDuration;
if(!sense) if(!sense)
@@ -460,8 +466,6 @@ public sealed partial class MediaScan
Localization.Core.READ_CD_error_0, Localization.Core.READ_CD_error_0,
Sense.PrettifySense(senseBuf.ToArray())); Sense.PrettifySense(senseBuf.ToArray()));
;
senseDecoded = Sense.Decode(senseBuf); senseDecoded = Sense.Decode(senseBuf);
if(senseDecoded.HasValue) if(senseDecoded.HasValue)
@@ -500,24 +504,20 @@ public sealed partial class MediaScan
} }
} }
sectorSpeedStart += blocksToRead; if(accumulatedSpeedMs >= 100)
{
double elapsed = _speedStopwatch.Elapsed.TotalSeconds; currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0));
if(elapsed <= 0) continue;
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
ScanSpeed?.Invoke(i, currentSpeed * 1024); ScanSpeed?.Invoke(i, currentSpeed * 1024);
sectorSpeedStart = 0; accumulatedSpeedMs = 0;
_speedStopwatch.Restart(); accumulatedSpeedSectors = 0;
}
} }
_speedStopwatch.Stop();
_scanStopwatch.Stop(); _scanStopwatch.Stop();
EndProgress?.Invoke(); EndProgress?.Invoke();
mhddLog.Close(); mhddLog.Close();
currentSpeed = sectorSpeedStart * blockSize / (1048576 * _speedStopwatch.Elapsed.TotalSeconds); currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0));
// ReSharper disable once CompareOfFloatsByEqualityOperator // ReSharper disable once CompareOfFloatsByEqualityOperator
if(results.MaxSpeed == double.MinValue) results.MaxSpeed = currentSpeed; if(results.MaxSpeed == double.MinValue) results.MaxSpeed = currentSpeed;
@@ -542,10 +542,10 @@ public sealed partial class MediaScan
InitBlockMap?.Invoke(results.Blocks, blockSize, scsiReader.BlocksToRead, currentProfile); InitBlockMap?.Invoke(results.Blocks, blockSize, scsiReader.BlocksToRead, currentProfile);
mhddLog = new MhddLog(_mhddLogPath, _dev, results.Blocks, blockSize, scsiReader.BlocksToRead, false); mhddLog = new MhddLog(_mhddLogPath, _dev, results.Blocks, blockSize, scsiReader.BlocksToRead, false);
ibgLog = new IbgLog(_ibgLogPath, currentProfile); ibgLog = new IbgLog(_ibgLogPath, currentProfile);
_speedStopwatch.Restart();
ulong sectorSpeedStart = 0;
InitProgress?.Invoke(); InitProgress?.Invoke();
uint accumulatedSpeedSectors = 0;
double accumulatedSpeedMs = 0;
for(ulong i = 0; i < results.Blocks; i += scsiReader.BlocksToRead) for(ulong i = 0; i < results.Blocks; i += scsiReader.BlocksToRead)
{ {
@@ -566,7 +566,11 @@ public sealed partial class MediaScan
(long)i, (long)i,
(long)results.Blocks); (long)results.Blocks);
_speedStopwatch.Restart();
sense = scsiReader.ReadBlocks(out _, i, blocksToRead, out double cmdDuration, out _, out _); sense = scsiReader.ReadBlocks(out _, i, blocksToRead, out double cmdDuration, out _, out _);
_speedStopwatch.Stop();
accumulatedSpeedMs += _speedStopwatch.ElapsedMilliseconds;
accumulatedSpeedSectors += blocksToRead;
results.ProcessingTime += cmdDuration; results.ProcessingTime += cmdDuration;
if(!sense && !_dev.Error) if(!sense && !_dev.Error)
@@ -616,23 +620,21 @@ public sealed partial class MediaScan
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
} }
sectorSpeedStart += blocksToRead; if(accumulatedSpeedMs >= 100)
{
double elapsed = _speedStopwatch.Elapsed.TotalSeconds; currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0));
if(elapsed <= 0) continue;
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
ScanSpeed?.Invoke(i, currentSpeed * 1024); ScanSpeed?.Invoke(i, currentSpeed * 1024);
sectorSpeedStart = 0; accumulatedSpeedMs = 0;
_speedStopwatch.Restart(); accumulatedSpeedSectors = 0;
}
} }
_speedStopwatch.Stop();
_scanStopwatch.Stop(); _scanStopwatch.Stop();
EndProgress?.Invoke(); EndProgress?.Invoke();
mhddLog.Close(); mhddLog.Close();
currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0));
ibgLog.Close(_dev, ibgLog.Close(_dev,
results.Blocks, results.Blocks,
blockSize, blockSize,
@@ -651,11 +653,11 @@ public sealed partial class MediaScan
InitProgress?.Invoke(); InitProgress?.Invoke();
for(int i = 0; i < seekTimes; i++) for(var i = 0; i < seekTimes; i++)
{ {
if(_aborted || !_seekTest) break; if(_aborted || !_seekTest) break;
uint seekPos = (uint)rnd.Next((int)results.Blocks); var seekPos = (uint)rnd.Next((int)results.Blocks);
PulseProgress?.Invoke(string.Format(Localization.Core.Seeking_to_sector_0, seekPos)); PulseProgress?.Invoke(string.Format(Localization.Core.Seeking_to_sector_0, seekPos));

View File

@@ -57,8 +57,8 @@ public sealed partial class MediaScan
const ushort sdProfile = 0x0001; const ushort sdProfile = 0x0001;
ushort blocksToRead = 128; ushort blocksToRead = 128;
uint blockSize = 512; uint blockSize = 512;
bool byteAddressed = true; var byteAddressed = true;
bool supportsCmd23 = false; var supportsCmd23 = false;
switch(_dev.Type) switch(_dev.Type)
{ {
@@ -214,9 +214,7 @@ public sealed partial class MediaScan
var rnd = new Random(); var rnd = new Random();
if(supportsCmd23 || blocksToRead == 1) if(supportsCmd23 || blocksToRead == 1)
{
UpdateStatus?.Invoke(string.Format(Localization.Core.Reading_0_sectors_at_a_time, blocksToRead)); UpdateStatus?.Invoke(string.Format(Localization.Core.Reading_0_sectors_at_a_time, blocksToRead));
}
else if(_useBufferedReads) else if(_useBufferedReads)
{ {
UpdateStatus?.Invoke(string.Format(Localization.Core.Reading_0_sectors_at_a_time_using_OS_buffered_reads, UpdateStatus?.Invoke(string.Format(Localization.Core.Reading_0_sectors_at_a_time_using_OS_buffered_reads,
@@ -233,9 +231,9 @@ public sealed partial class MediaScan
var ibgLog = new IbgLog(_ibgLogPath, sdProfile); var ibgLog = new IbgLog(_ibgLogPath, sdProfile);
_scanStopwatch.Restart(); _scanStopwatch.Restart();
_speedStopwatch.Restart();
ulong sectorSpeedStart = 0;
InitProgress?.Invoke(); InitProgress?.Invoke();
uint accumulatedSpeedSectors = 0;
double accumulatedSpeedMs = 0;
for(ulong i = 0; i < results.Blocks; i += blocksToRead) for(ulong i = 0; i < results.Blocks; i += blocksToRead)
{ {
@@ -256,6 +254,8 @@ public sealed partial class MediaScan
bool error; bool error;
_speedStopwatch.Restart();
if(blocksToRead == 1) if(blocksToRead == 1)
{ {
error = _dev.ReadSingleBlock(out cmdBuf, error = _dev.ReadSingleBlock(out cmdBuf,
@@ -291,6 +291,10 @@ public sealed partial class MediaScan
out duration); out duration);
} }
_speedStopwatch.Stop();
accumulatedSpeedMs += _speedStopwatch.ElapsedMilliseconds;
accumulatedSpeedSectors += blocksToRead;
if(!error) if(!error)
{ {
switch(duration) switch(duration)
@@ -337,23 +341,21 @@ public sealed partial class MediaScan
ibgLog.Write(i, 0); ibgLog.Write(i, 0);
} }
sectorSpeedStart += blocksToRead; if(accumulatedSpeedMs >= 100)
{
double elapsed = _speedStopwatch.Elapsed.TotalSeconds; currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0));
if(elapsed <= 0) continue;
currentSpeed = sectorSpeedStart * blockSize / (1048576 * elapsed);
ScanSpeed?.Invoke(i, currentSpeed * 1024); ScanSpeed?.Invoke(i, currentSpeed * 1024);
sectorSpeedStart = 0; accumulatedSpeedMs = 0;
_speedStopwatch.Restart(); accumulatedSpeedSectors = 0;
}
} }
_speedStopwatch.Stop();
_scanStopwatch.Stop(); _scanStopwatch.Stop();
EndProgress?.Invoke(); EndProgress?.Invoke();
mhddLog.Close(); mhddLog.Close();
currentSpeed = accumulatedSpeedSectors * blockSize / (1048576 * (accumulatedSpeedMs / 1000.0));
ibgLog.Close(_dev, ibgLog.Close(_dev,
results.Blocks, results.Blocks,
blockSize, blockSize,
@@ -364,11 +366,11 @@ public sealed partial class MediaScan
InitProgress?.Invoke(); InitProgress?.Invoke();
for(int i = 0; i < seekTimes; i++) for(var i = 0; i < seekTimes; i++)
{ {
if(_aborted || !_seekTest) break; if(_aborted || !_seekTest) break;
uint seekPos = (uint)rnd.Next((int)results.Blocks); var seekPos = (uint)rnd.Next((int)results.Blocks);
PulseProgress?.Invoke(string.Format(Localization.Core.Seeking_to_sector_0, seekPos)); PulseProgress?.Invoke(string.Format(Localization.Core.Seeking_to_sector_0, seekPos));