使用
System.Diagnostics.PerformanceCounter
类,连接到与正在索引的驱动器相关的 PhysicalDisk 计数器。
以下是一些代码示例,尽管它目前是硬编码到"C:"驱动器,但您需要将“C:”更改为您的进程正在扫描的任何驱动器。(这只是大致的示范代码,用于说明性能计数器的存在 - 不要将其视为提供准确信息 - 应仅用作指南。按照自己的目的进行更改)
观察
% 空闲时间 计数器,该计数器指示驱动器在多大程度上在执行操作。
0%空闲 表示磁盘正在忙碌,但不一定意味着它无法传输更多数据。
将
% 空闲时间 与
当前磁盘队列长度 结合起来,这将告诉您驱动器是否变得如此繁忙,以至于无法处理所有的数据请求。通常情况下,任何超过 0 的值都表示驱动器可能已经非常忙碌,而任何超过 2 的值都表示驱动器已经完全饱和了。这些规则对SSD和HDD都适用。
此外,您读取的任何值都是某个时间点上的瞬时值。您应该对一些结果进行一个运行平均数,例如每100毫秒读取一次,并在使用结果的信息做出决策之前对5个读数求平均数(即等待计数器稳定后再进行下一次IO请求)。
internal DiskUsageMonitor(string driveName)
{
var perfCategory = new PerformanceCounterCategory("PhysicalDisk");
string[] instanceNames = perfCategory.GetInstanceNames();
foreach (string name in instanceNames)
{
if (name.IndexOf("C:") > 0)
{
if (string.IsNullOrEmpty(driveName))
driveName = name;
}
}
_readBytesCounter = new PerformanceCounter("PhysicalDisk",
"Disk Read Bytes/sec",
driveName);
_writeBytesCounter = new PerformanceCounter("PhysicalDisk",
"Disk Write Bytes/sec",
driveName);
_diskQueueCounter = new PerformanceCounter("PhysicalDisk",
"Current Disk Queue Length",
driveName);
_idleCounter = new PerformanceCounter("PhysicalDisk",
"% Idle Time",
driveName);
InitTimer();
}
internal event DiskUsageResultHander DiskUsageResult;
private void InitTimer()
{
StopTimer();
_perfTimer = new Timer(_updateResolutionMillisecs);
_perfTimer.Elapsed += PerfTimerElapsed;
_perfTimer.Start();
}
private void PerfTimerElapsed(object sender, ElapsedEventArgs e)
{
float diskReads = _readBytesCounter.NextValue();
float diskWrites = _writeBytesCounter.NextValue();
float diskQueue = _diskQueueCounter.NextValue();
float idlePercent = _idleCounter.NextValue();
if (idlePercent > 100)
{
idlePercent = 100;
}
if (DiskUsageResult != null)
{
var stats = new DiskUsageStats
{
DriveName = _readBytesCounter.InstanceName,
DiskQueueLength = (int)diskQueue,
ReadBytesPerSec = (int)diskReads,
WriteBytesPerSec = (int)diskWrites,
DiskUsagePercent = 100 - (int)idlePercent
};
DiskUsageResult(stats);
}
}