Skip to content

Commit b19b613

Browse files
fix: use uncached reads even with --sync mode
1 parent 78712c4 commit b19b613

File tree

2 files changed

+23
-14
lines changed

2 files changed

+23
-14
lines changed

pkg/dperf/perf.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,9 @@ func (d *DrivePerf) runTests(ctx context.Context, path string, testUUID string)
5555

5656
dataBuffers := make([][]byte, d.IOPerDrive)
5757
for i := 0; i < d.IOPerDrive; i++ {
58-
// In sync mode or with small block sizes, use regular buffer allocation
59-
// Otherwise, use aligned blocks for O_DIRECT
60-
if d.SyncMode {
61-
dataBuffers[i] = make([]byte, d.BlockSize)
62-
} else {
63-
dataBuffers[i] = alignedBlock(int(d.BlockSize))
64-
}
58+
// Use aligned blocks when block size supports O_DIRECT (>= 4KiB)
59+
// For smaller block sizes, aligned blocks are still fine (they're just regular buffers with alignment)
60+
dataBuffers[i] = alignedBlock(int(d.BlockSize))
6561
}
6662

6763
testUUIDPath := filepath.Join(path, testUUID)

pkg/dperf/run_linux.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ func (n nullWriter) Write(b []byte) (int, error) {
4040
func (d *DrivePerf) runReadTest(ctx context.Context, path string, data []byte) (uint64, error) {
4141
startTime := time.Now()
4242

43-
// Choose flags based on sync mode
43+
// For reads, prefer O_DIRECT to bypass page cache when possible
44+
// For small block sizes (< 4KiB), use regular I/O with FADV_DONTNEED to drop cache
4445
var flags int
45-
if d.SyncMode {
46-
// Use O_SYNC for synchronized reads (for small block sizes or when --sync is specified)
47-
flags = syscall.O_SYNC | os.O_RDONLY
48-
} else {
49-
// Use O_DIRECT for direct I/O (bypasses page cache)
46+
useDirectIO := d.BlockSize >= DirectioAlignSize
47+
if useDirectIO {
5048
flags = syscall.O_DIRECT | os.O_RDONLY
49+
} else {
50+
flags = os.O_RDONLY
5151
}
5252

5353
r, err := os.OpenFile(path, flags, 0o400)
@@ -56,7 +56,12 @@ func (d *DrivePerf) runReadTest(ctx context.Context, path string, data []byte) (
5656
}
5757
unix.Fadvise(int(r.Fd()), 0, int64(d.FileSize), unix.FADV_SEQUENTIAL)
5858

59-
n, err := copyAligned(&nullWriter{}, r, data, int64(d.FileSize), r.Fd(), d.SyncMode)
59+
// For non-O_DIRECT reads, advise kernel to not cache the data
60+
if !useDirectIO {
61+
unix.Fadvise(int(r.Fd()), 0, int64(d.FileSize), unix.FADV_DONTNEED)
62+
}
63+
64+
n, err := copyAligned(&nullWriter{}, r, data, int64(d.FileSize), r.Fd(), !useDirectIO)
6065
r.Close()
6166
if err != nil {
6267
return 0, err
@@ -65,6 +70,14 @@ func (d *DrivePerf) runReadTest(ctx context.Context, path string, data []byte) (
6570
return 0, fmt.Errorf("Expected read %d, read %d", d.FileSize, n)
6671
}
6772

73+
// Drop any cached pages after reading to ensure future reads are also uncached
74+
if !useDirectIO {
75+
if f, err := os.Open(path); err == nil {
76+
unix.Fadvise(int(f.Fd()), 0, 0, unix.FADV_DONTNEED)
77+
f.Close()
78+
}
79+
}
80+
6881
dt := float64(time.Since(startTime))
6982
throughputInSeconds := (float64(d.FileSize) / dt) * float64(time.Second)
7083
return uint64(throughputInSeconds), nil

0 commit comments

Comments
 (0)