@@ -40,14 +40,14 @@ func (n nullWriter) Write(b []byte) (int, error) {
4040func (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