Skip to content

Commit 6654bb9

Browse files
committed
Add prefetching support on macOS
macOS doesn't have posix_fadvise(), but fcntl() with the F_RDADVISE command does the same thing. Some related documentation has been generalized to not mention posix_advise() specifically anymore. Reviewed-by: Thomas Munro <thomas.munro@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/0827edec-1317-4917-a186-035eb1e3241d%40eisentraut.org
1 parent 2e6a804 commit 6654bb9

File tree

6 files changed

+54
-35
lines changed

6 files changed

+54
-35
lines changed

doc/src/sgml/config.sgml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2679,11 +2679,9 @@ include_dir 'conf.d'
26792679
</para>
26802680

26812681
<para>
2682-
Asynchronous I/O depends on an effective <function>posix_fadvise</function>
2683-
function, which some operating systems lack. If the function is not
2684-
present then setting this parameter to anything but zero will result
2685-
in an error. On some operating systems (e.g., Solaris), the function
2686-
is present but does not actually do anything.
2682+
Asynchronous I/O requires that the operating system supports issuing
2683+
read-ahead advice. If there is no operating system support then
2684+
setting this parameter to anything but zero will result in an error.
26872685
</para>
26882686

26892687
<para>
@@ -3852,10 +3850,8 @@ include_dir 'conf.d'
38523850
<literal>off</literal>, <literal>on</literal> and
38533851
<literal>try</literal> (the default). The setting
38543852
<literal>try</literal> enables
3855-
prefetching only if the operating system provides the
3856-
<function>posix_fadvise</function> function, which is currently used
3857-
to implement prefetching. Note that some operating systems provide the
3858-
function, but it doesn't do anything.
3853+
prefetching only if the operating system provides support for issuing
3854+
read-ahead advice.
38593855
</para>
38603856
<para>
38613857
Prefetching blocks that will soon be needed can reduce I/O wait times

doc/src/sgml/wal.sgml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -841,8 +841,8 @@
841841
The <xref linkend="guc-maintenance-io-concurrency"/> and
842842
<xref linkend="guc-wal-decode-buffer-size"/> settings limit prefetching
843843
concurrency and distance, respectively. By default, it is set to
844-
<literal>try</literal>, which enables the feature on systems where
845-
<function>posix_fadvise</function> is available.
844+
<literal>try</literal>, which enables the feature on systems that support
845+
issuing read-ahead advice.
846846
</para>
847847
</sect1>
848848

src/backend/commands/variable.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,7 +1212,7 @@ check_effective_io_concurrency(int *newval, void **extra, GucSource source)
12121212
#ifndef USE_PREFETCH
12131213
if (*newval != 0)
12141214
{
1215-
GUC_check_errdetail("\"effective_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise().");
1215+
GUC_check_errdetail("\"effective_io_concurrency\" must be set to 0 on platforms that lack support for issuing read-ahead advice.");
12161216
return false;
12171217
}
12181218
#endif /* USE_PREFETCH */
@@ -1225,7 +1225,7 @@ check_maintenance_io_concurrency(int *newval, void **extra, GucSource source)
12251225
#ifndef USE_PREFETCH
12261226
if (*newval != 0)
12271227
{
1228-
GUC_check_errdetail("\"maintenance_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise().");
1228+
GUC_check_errdetail("\"maintenance_io_concurrency\" must be set to 0 on platforms that lack support for issuing read-ahead advice.");
12291229
return false;
12301230
}
12311231
#endif /* USE_PREFETCH */

src/backend/storage/file/fd.c

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2068,40 +2068,59 @@ FileClose(File file)
20682068
/*
20692069
* FilePrefetch - initiate asynchronous read of a given range of the file.
20702070
*
2071-
* Currently the only implementation of this function is using posix_fadvise
2072-
* which is the simplest standardized interface that accomplishes this.
2073-
* We could add an implementation using libaio in the future; but note that
2074-
* this API is inappropriate for libaio, which wants to have a buffer provided
2075-
* to read into.
2071+
* Returns 0 on success, otherwise an errno error code (like posix_fadvise()).
2072+
*
2073+
* posix_fadvise() is the simplest standardized interface that accomplishes
2074+
* this.
20762075
*/
20772076
int
20782077
FilePrefetch(File file, off_t offset, off_t amount, uint32 wait_event_info)
20792078
{
2080-
#if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
2081-
int returnCode;
2082-
20832079
Assert(FileIsValid(file));
20842080

20852081
DO_DB(elog(LOG, "FilePrefetch: %d (%s) " INT64_FORMAT " " INT64_FORMAT,
20862082
file, VfdCache[file].fileName,
20872083
(int64) offset, (int64) amount));
20882084

2089-
returnCode = FileAccess(file);
2090-
if (returnCode < 0)
2091-
return returnCode;
2085+
#if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
2086+
{
2087+
int returnCode;
2088+
2089+
returnCode = FileAccess(file);
2090+
if (returnCode < 0)
2091+
return returnCode;
20922092

20932093
retry:
2094-
pgstat_report_wait_start(wait_event_info);
2095-
returnCode = posix_fadvise(VfdCache[file].fd, offset, amount,
2096-
POSIX_FADV_WILLNEED);
2097-
pgstat_report_wait_end();
2094+
pgstat_report_wait_start(wait_event_info);
2095+
returnCode = posix_fadvise(VfdCache[file].fd, offset, amount,
2096+
POSIX_FADV_WILLNEED);
2097+
pgstat_report_wait_end();
20982098

2099-
if (returnCode == EINTR)
2100-
goto retry;
2099+
if (returnCode == EINTR)
2100+
goto retry;
21012101

2102-
return returnCode;
2102+
return returnCode;
2103+
}
2104+
#elif defined(__darwin__)
2105+
{
2106+
struct radvisory
2107+
{
2108+
off_t ra_offset; /* offset into the file */
2109+
int ra_count; /* size of the read */
2110+
} ra;
2111+
int returnCode;
2112+
2113+
ra.ra_offset = offset;
2114+
ra.ra_count = amount;
2115+
pgstat_report_wait_start(wait_event_info);
2116+
returnCode = fcntl(VfdCache[file].fd, F_RDADVISE, &ra);
2117+
pgstat_report_wait_end();
2118+
if (returnCode != -1)
2119+
return 0;
2120+
else
2121+
return errno;
2122+
}
21032123
#else
2104-
Assert(FileIsValid(file));
21052124
return 0;
21062125
#endif
21072126
}

src/include/pg_config_manual.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,8 @@
139139
/*
140140
* USE_PREFETCH code should be compiled only if we have a way to implement
141141
* prefetching. (This is decoupled from USE_POSIX_FADVISE because there
142-
* might in future be support for alternative low-level prefetch APIs.
143-
* If you change this, you probably need to adjust the error message in
144-
* check_effective_io_concurrency.)
142+
* might in future be support for alternative low-level prefetch APIs,
143+
* as well as platform-specific APIs defined elsewhere.)
145144
*/
146145
#ifdef USE_POSIX_FADVISE
147146
#define USE_PREFETCH

src/include/port/darwin.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@
66
#define HAVE_FSYNC_WRITETHROUGH
77

88
#endif
9+
10+
/*
11+
* macOS has a platform-specific implementation of prefetching.
12+
*/
13+
#define USE_PREFETCH

0 commit comments

Comments
 (0)