Skip to content

Commit bb00a0b

Browse files
committed
mac: improve posix_fadvise shim
This builds upon the best effort macOS cache invalidation work by DeveloperEcosystemEngineering@apple.com's by shimming even more of posix_advise() on macOS: - POSIX_FADV_NORMAL is ignored - POSIX_FADV_SEQUENTIAL/POSIX_FADV_RANDOM are mapped to enable/disable readahead via fcntl(..., F_RDAHEAD, ...) To paraphrase from the commit that was done for similar reasons targeting Windows (see 8300eba ("windowsaio: add best effort cache invalidation")): This change may make default bandwidth speeds on macOS look lower compared to older versions of fio but this matches the behaviour of fio on other platforms with invalidation (such as Linux) because we are trying to avoid measuring cache reuse (unless invalidate=0 is set). The impact of invalidation is demonstrated by the bandwidths achieved by the following jobs running on a SSD of an otherwise idle Intel Mac with 16GBytes of RAM: ./fio --stonewall --size=128M --ioengine=posixaio --filename=fio.tmp --iodepth=64 \ --bs=4k --invalidate=0 --direct=0 \ --name=create --rw=write \ --name=cached --rw=randread --loops=2 \ --name=invalidated --rw=randread --loops=2 --invalidate=1 [...] cached: (groupid=1, jobs=1): err= 0: pid=32517: Sat May 17 18:37:57 2025 read: IOPS=228k, BW=892MiB/s (935MB/s)(256MiB/287msec) [...] invalidated: (groupid=2, jobs=1): err= 0: pid=32518: Sat May 17 18:37:57 2025 read: IOPS=43.1k, BW=168MiB/s (176MB/s)(256MiB/1522msec) The impact of being able to tune readahead can be seen below: ./fio --filename=fio.tmp --stonewall --size=128M --filename=fio.tmp --bs=4k \ --name=precache --rw=read --bs=128k \ --name=cached --rw=read \ --name=uncached-readahead --rw=read --invalidate=1 \ --name=uncached-no-readahead --rw=read --invalidate=1 --fadvise=random [...] cached: (groupid=1, jobs=1): err= 0: pid=32600: Sat May 17 18:49:22 2025 read: IOPS=349k, BW=1362MiB/s (1428MB/s)(128MiB/94msec) -- uncached-readahead: (groupid=2, jobs=1): err= 0: pid=32601: Sat May 17 18:49:22 2025 read: IOPS=315k, BW=1231MiB/s (1291MB/s)(128MiB/104msec) -- uncached-no-readahead: (groupid=3, jobs=1): err= 0: pid=32602: Sat May 17 18:49:22 2025 read: IOPS=40.8k, BW=159MiB/s (167MB/s)(128MiB/803msec) Signed-off-by: Sitsofe Wheeler <sitsofe@yahoo.com>
1 parent 6979c18 commit bb00a0b

File tree

3 files changed

+45
-23
lines changed

3 files changed

+45
-23
lines changed

helpers.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,9 @@ int sync_file_range(int fd, uint64_t offset, uint64_t nbytes,
2626
}
2727
#endif
2828

29-
#if defined (__APPLE__)
30-
int posix_fadvise(int fd, off_t offset, off_t len, int advice)
31-
{
32-
if (advice == POSIX_FADV_DONTNEED)
33-
return discard_pages(fd, offset, len);
34-
errno = EINVAL;
35-
return -1;
36-
}
37-
#else
3829
#ifndef CONFIG_POSIX_FADVISE
3930
int posix_fadvise(int fd, off_t offset, off_t len, int advice)
4031
{
4132
return 0;
4233
}
4334
#endif
44-
#endif /* defined (__APPLE__) */

os/os-mac.h

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <errno.h>
77
#include <fcntl.h>
88
#include <sys/disk.h>
9+
#include <sys/mman.h>
910
#include <sys/sysctl.h>
1011
#include <sys/time.h>
1112
#include <unistd.h>
@@ -14,8 +15,6 @@
1415
#include <machine/endian.h>
1516
#include <libkern/OSByteOrder.h>
1617

17-
#include <sys/stat.h>
18-
#include <sys/mman.h>
1918
#include <stdio.h>
2019

2120

@@ -135,13 +134,6 @@ static inline int discard_pages(int fd, off_t offset, off_t size)
135134
caddr_t *addr;
136135
uint64_t chunk_size = MMAP_CHUNK_SIZE;
137136

138-
if (fsync(fd) < 0) {
139-
int __err = errno;
140-
log_err("%s: Cannot fsync file: %s \n", __func__, strerror(errno));
141-
errno = __err;
142-
return -1;
143-
}
144-
145137
/*
146138
* mmap the file in 1GB chunks and msync(MS_INVALIDATE).
147139
*/
@@ -154,22 +146,22 @@ static inline int discard_pages(int fd, off_t offset, off_t size)
154146
fprintf(stderr, "Failed to mmap (%s), offset = %llu, size = %llu\n",
155147
strerror(errno), offset, mmap_size);
156148
errno = __map_errno;
157-
return -1;
149+
return errno;
158150
}
159151

160152
if (msync(addr, mmap_size, MS_INVALIDATE)) {
161153
int __msync_errno = errno;
162154
fprintf(stderr, "msync failed to free cache pages.\n");
163155
errno = __msync_errno;
164-
return -1;
156+
return errno;
165157
}
166158

167159
/* Destroy the above mappings used to invalidate cache - cleaning up */
168160
if (munmap(addr, mmap_size) < 0) {
169161
int __munmap_errno = errno;
170162
fprintf(stderr, "munmap failed, error = %d.\n", errno);
171163
errno = __munmap_errno;
172-
return -1;
164+
return errno;
173165
}
174166

175167
size -= mmap_size;
@@ -178,3 +170,43 @@ static inline int discard_pages(int fd, off_t offset, off_t size)
178170

179171
return 0;
180172
}
173+
174+
static inline int set_readhead(int fd, bool enabled) {
175+
int ret;
176+
177+
ret = fcntl(fd, F_RDAHEAD, enabled ? 1 : 0);
178+
if (ret == -1) {
179+
ret = errno;
180+
}
181+
182+
return ret;
183+
}
184+
185+
#define CONFIG_POSIX_FADVISE
186+
#define POSIX_FADV_NORMAL (0)
187+
#define POSIX_FADV_RANDOM (1)
188+
#define POSIX_FADV_SEQUENTIAL (2)
189+
#define POSIX_FADV_DONTNEED (4)
190+
static inline int posix_fadvise(int fd, off_t offset, off_t len, int advice)
191+
{
192+
int ret;
193+
194+
switch(advice) {
195+
case POSIX_FADV_NORMAL:
196+
ret = 0;
197+
break;
198+
case POSIX_FADV_RANDOM:
199+
ret = set_readhead(fd, false);
200+
break;
201+
case POSIX_FADV_SEQUENTIAL:
202+
ret = set_readhead(fd, true);
203+
break;
204+
case POSIX_FADV_DONTNEED:
205+
ret = discard_pages(fd, offset, len);
206+
break;
207+
default:
208+
ret = EINVAL;
209+
}
210+
211+
return ret;
212+
}

t/run-fio-tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ def check_result(self):
946946
'test_id': 35,
947947
'test_class': FioJobFileTest,
948948
'job': 't0035.fio',
949-
'success': SUCCESS_STDERR,
949+
'success': SUCCESS_DEFAULT,
950950
'pre_job': None,
951951
'pre_success': None,
952952
'requirements': [],

0 commit comments

Comments
 (0)