sqlinsight-pro/tests/SQLInsight.Core.Tests/DiskTests.cs
Søren Eggert Lundsteen Olsen ac13e3d826 Disk speed per drive: IOPS, MB/s and latency
- file-io records each file's drive: sys.dm_os_volume_stats from 2008 R2 SP1
  (new capability VolumeStats, mount points included), otherwise derived
  from the path (D:\..., \server\share\, / on Linux), so 2005 works too
- migration 0007: Volume and IntervalSeconds on FileIoSamples, and
  DiskHourly (rolled up by maintenance, kept HourlyDays)
- DiskActivity sums files per drive: read/write IOPS, MB/s and latency
  weighted by I/O count
- instance page: "Diskhastighed pr. drev" (table and MB/s + latency charts);
  time window analysis and its PDF: per drive against the same hours of the
  four previous weeks
- SQLI-IO-001/002 now report per drive (one finding when the storage is
  slow, the slowest files in the evidence) instead of per file

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 08:03:11 +02:00

64 lines
2.4 KiB
C#

using SQLInsight.Core.Data;
namespace SQLInsight.Core.Tests;
public class DiskTests
{
[Theory]
[InlineData(@"D:\SQLData\Sales.mdf", @"D:\")]
[InlineData(@"l:\Logs\Sales_log.ldf", @"L:\")]
[InlineData(@"\\nas01\sql\Sales.mdf", @"\\nas01\sql\")]
[InlineData("/var/opt/mssql/data/master.mdf", "/")]
public void Drive_is_derived_from_the_file_path(string physicalName, string volume) =>
Assert.Equal(volume, DiskVolumes.FromPhysicalName(physicalName));
[Fact]
public void Reported_volume_wins_over_the_path()
{
var mountPoint = File("Sales", 1, "ROWS", @"D:\Mounts\Data1\Sales.mdf") with { Volume = @"D:\Mounts\Data1\" };
Assert.Equal(@"D:\Mounts\Data1\", DiskVolumes.Of(mountPoint));
Assert.Equal(@"D:\", DiskVolumes.Of(mountPoint with { Volume = null }));
}
[Fact]
public void Files_are_summed_per_drive_with_rates_and_weighted_latency()
{
var files = new[]
{
File("Sales", 1, "ROWS", @"D:\Sales.mdf", reads: 3000, bytesRead: 300 * 1048576L, readStall: 30_000),
File("Stock", 1, "ROWS", @"D:\Stock.mdf", reads: 1000, bytesRead: 0, readStall: 50_000),
File("Sales", 2, "LOG", @"L:\Sales_log.ldf", writes: 6000, bytesWritten: 60 * 1048576L, writeStall: 12_000),
};
var disks = DiskActivity.ByVolume(files, seconds: 300);
Assert.Equal([@"D:\", @"L:\"], disks.Select(d => d.Volume));
var data = disks[0];
Assert.Equal(2, data.DataFiles);
Assert.Equal(0, data.LogFiles);
Assert.Equal(4000 / 300.0, data.ReadIops);
Assert.Equal(1.0, data.ReadMbPerSecond);
Assert.Equal(20, data.AverageReadMs); // 80 s over 4000 reads, not the average of 10 and 50 ms
Assert.Null(data.AverageWriteMs);
var log = disks[1];
Assert.Equal(20, log.WriteIops);
Assert.Equal(0.2, log.WriteMbPerSecond!.Value, 6);
Assert.Equal(2, log.AverageWriteMs);
}
private static FileIoStat File(string db, int id, string type, string path, long reads = 0, long bytesRead = 0, long readStall = 0,
long writes = 0, long bytesWritten = 0, long writeStall = 0) => new()
{
DatabaseName = db,
FileId = id,
FileType = type,
PhysicalName = path,
Reads = reads,
BytesRead = bytesRead,
ReadStallMs = readStall,
Writes = writes,
BytesWritten = bytesWritten,
WriteStallMs = writeStall,
};
}