private void FillInfo(DiskUsageInfo toFill, DiskStats previousDiskStats, DiskStats diskStats, double deltaSeconds) { var readsDelta = diskStats.ReadsCount - previousDiskStats.ReadsCount; var writesDelta = diskStats.WritesCount - previousDiskStats.WritesCount; var sectorsReadDelta = diskStats.SectorsReadCount - previousDiskStats.SectorsReadCount; var sectorsWrittenDelta = diskStats.SectorsWrittenCount - previousDiskStats.SectorsWrittenCount; var msReadDelta = diskStats.MsSpentReading - previousDiskStats.MsSpentReading; var msWriteDelta = diskStats.MsSpentWriting - previousDiskStats.MsSpentWriting; var msSpentDoingIoDelta = diskStats.MsSpentDoingIo - previousDiskStats.MsSpentDoingIo; if (readsDelta > 0) { toFill.ReadAverageMsLatency = (long)((double)msReadDelta / readsDelta); } if (writesDelta > 0) { toFill.WriteAverageMsLatency = (long)((double)msWriteDelta / writesDelta); } toFill.CurrentQueueLength = diskStats.CurrentQueueLength; if (deltaSeconds > 0d) { toFill.ReadsPerSecond = (long)(readsDelta / deltaSeconds); toFill.WritesPerSecond = (long)(writesDelta / deltaSeconds); // NOTE: Every sector equals 512B, so it's easy to convert these values. // NOTE: See https://www.man7.org/linux/man-pages/man1/iostat.1.html for details about sector size. toFill.BytesReadPerSecond = (long)(sectorsReadDelta * 512d / deltaSeconds); toFill.BytesWrittenPerSecond = (long)(sectorsWrittenDelta * 512d / deltaSeconds); toFill.UtilizedPercent = (100d * msSpentDoingIoDelta / (deltaSeconds * 1000)).Clamp(0, 100); } }
private DiskStats[] GetDiskCountersWindows() { DiskStats[] diskStats = new DiskStats[m_drives.Length]; for (int i = 0; i < m_drives.Length; i++) { var drive = m_drives[i]; if (!drive.Item2.IsClosed && !drive.Item2.IsInvalid) { uint bytesReturned; diskStats[i].DiskPerformance = default(DISK_PERFORMANCE); try { bool result = DeviceIoControl(drive.Item2, IOCTL_DISK_PERFORMANCE, inputBuffer: IntPtr.Zero, inputBufferSize: 0, outputBuffer: out diskStats[i].DiskPerformance, outputBufferSize: Marshal.SizeOf(typeof(DISK_PERFORMANCE)), bytesReturned: out bytesReturned, overlapped: IntPtr.Zero); if (result && drive.Item1.TotalSize != 0) { diskStats[i].AvailableSpaceGb = BytesToGigaBytes(drive.Item1.AvailableFreeSpace); } } catch (ObjectDisposedException) { // Occasionally the handle is disposed even though it's checked against being closed and valid // above. In those cases, just catch the failure and continue on to avoid crashes } } } return(diskStats); }
private List <DiskStats> ParseDiskstats(IEnumerable <string> diskstats) { var disksStats = new List <DiskStats>(); try { foreach (var line in diskstats) { // NOTE: In the most basic form there are 14 parts. // NOTE: See https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats for details. if (FileParser.TrySplitLine(line, 14, out var parts) && IsDiskNumber(parts[0]) && IsWholeDiskNumber(parts[1])) { var stats = new DiskStats { DiskName = parts[2] }; if (long.TryParse(parts[3], out var readsCount)) { stats.ReadsCount = readsCount; } if (long.TryParse(parts[5], out var sectorsRead)) { stats.SectorsReadCount = sectorsRead; } if (long.TryParse(parts[6], out var msSpentReading)) { stats.MsSpentReading = msSpentReading; } if (long.TryParse(parts[7], out var writesCount)) { stats.WritesCount = writesCount; } if (long.TryParse(parts[9], out var sectorsWritten)) { stats.SectorsWrittenCount = sectorsWritten; } if (long.TryParse(parts[10], out var msSpentWriting)) { stats.MsSpentWriting = msSpentWriting; } if (long.TryParse(parts[11], out var currentQueueLength)) { stats.CurrentQueueLength = currentQueueLength; } if (long.TryParse(parts[12], out var msSpentDoingIo)) { stats.MsSpentDoingIo = msSpentDoingIo; } disksStats.Add(stats); } } } catch (Exception error) { InternalErrorLogger.Warn(error); } return(disksStats); }