1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-29 13:56:47 +03:00

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
This commit is contained in:
Peter Eisentraut 2024-08-28 07:26:48 +02:00
parent 2e6a8047f0
commit 6654bb9204
6 changed files with 54 additions and 35 deletions

View File

@ -2679,11 +2679,9 @@ include_dir 'conf.d'
</para> </para>
<para> <para>
Asynchronous I/O depends on an effective <function>posix_fadvise</function> Asynchronous I/O requires that the operating system supports issuing
function, which some operating systems lack. If the function is not read-ahead advice. If there is no operating system support then
present then setting this parameter to anything but zero will result setting this parameter to anything but zero will result in an error.
in an error. On some operating systems (e.g., Solaris), the function
is present but does not actually do anything.
</para> </para>
<para> <para>
@ -3852,10 +3850,8 @@ include_dir 'conf.d'
<literal>off</literal>, <literal>on</literal> and <literal>off</literal>, <literal>on</literal> and
<literal>try</literal> (the default). The setting <literal>try</literal> (the default). The setting
<literal>try</literal> enables <literal>try</literal> enables
prefetching only if the operating system provides the prefetching only if the operating system provides support for issuing
<function>posix_fadvise</function> function, which is currently used read-ahead advice.
to implement prefetching. Note that some operating systems provide the
function, but it doesn't do anything.
</para> </para>
<para> <para>
Prefetching blocks that will soon be needed can reduce I/O wait times Prefetching blocks that will soon be needed can reduce I/O wait times

View File

@ -841,8 +841,8 @@
The <xref linkend="guc-maintenance-io-concurrency"/> and The <xref linkend="guc-maintenance-io-concurrency"/> and
<xref linkend="guc-wal-decode-buffer-size"/> settings limit prefetching <xref linkend="guc-wal-decode-buffer-size"/> settings limit prefetching
concurrency and distance, respectively. By default, it is set to concurrency and distance, respectively. By default, it is set to
<literal>try</literal>, which enables the feature on systems where <literal>try</literal>, which enables the feature on systems that support
<function>posix_fadvise</function> is available. issuing read-ahead advice.
</para> </para>
</sect1> </sect1>

View File

@ -1212,7 +1212,7 @@ check_effective_io_concurrency(int *newval, void **extra, GucSource source)
#ifndef USE_PREFETCH #ifndef USE_PREFETCH
if (*newval != 0) if (*newval != 0)
{ {
GUC_check_errdetail("\"effective_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise()."); GUC_check_errdetail("\"effective_io_concurrency\" must be set to 0 on platforms that lack support for issuing read-ahead advice.");
return false; return false;
} }
#endif /* USE_PREFETCH */ #endif /* USE_PREFETCH */
@ -1225,7 +1225,7 @@ check_maintenance_io_concurrency(int *newval, void **extra, GucSource source)
#ifndef USE_PREFETCH #ifndef USE_PREFETCH
if (*newval != 0) if (*newval != 0)
{ {
GUC_check_errdetail("\"maintenance_io_concurrency\" must be set to 0 on platforms that lack posix_fadvise()."); GUC_check_errdetail("\"maintenance_io_concurrency\" must be set to 0 on platforms that lack support for issuing read-ahead advice.");
return false; return false;
} }
#endif /* USE_PREFETCH */ #endif /* USE_PREFETCH */

View File

@ -2068,40 +2068,59 @@ FileClose(File file)
/* /*
* FilePrefetch - initiate asynchronous read of a given range of the file. * FilePrefetch - initiate asynchronous read of a given range of the file.
* *
* Currently the only implementation of this function is using posix_fadvise * Returns 0 on success, otherwise an errno error code (like posix_fadvise()).
* which is the simplest standardized interface that accomplishes this. *
* We could add an implementation using libaio in the future; but note that * posix_fadvise() is the simplest standardized interface that accomplishes
* this API is inappropriate for libaio, which wants to have a buffer provided * this.
* to read into.
*/ */
int int
FilePrefetch(File file, off_t offset, off_t amount, uint32 wait_event_info) FilePrefetch(File file, off_t offset, off_t amount, uint32 wait_event_info)
{ {
#if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
int returnCode;
Assert(FileIsValid(file)); Assert(FileIsValid(file));
DO_DB(elog(LOG, "FilePrefetch: %d (%s) " INT64_FORMAT " " INT64_FORMAT, DO_DB(elog(LOG, "FilePrefetch: %d (%s) " INT64_FORMAT " " INT64_FORMAT,
file, VfdCache[file].fileName, file, VfdCache[file].fileName,
(int64) offset, (int64) amount)); (int64) offset, (int64) amount));
returnCode = FileAccess(file); #if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
if (returnCode < 0) {
return returnCode; int returnCode;
returnCode = FileAccess(file);
if (returnCode < 0)
return returnCode;
retry: retry:
pgstat_report_wait_start(wait_event_info); pgstat_report_wait_start(wait_event_info);
returnCode = posix_fadvise(VfdCache[file].fd, offset, amount, returnCode = posix_fadvise(VfdCache[file].fd, offset, amount,
POSIX_FADV_WILLNEED); POSIX_FADV_WILLNEED);
pgstat_report_wait_end(); pgstat_report_wait_end();
if (returnCode == EINTR) if (returnCode == EINTR)
goto retry; goto retry;
return returnCode; return returnCode;
}
#elif defined(__darwin__)
{
struct radvisory
{
off_t ra_offset; /* offset into the file */
int ra_count; /* size of the read */
} ra;
int returnCode;
ra.ra_offset = offset;
ra.ra_count = amount;
pgstat_report_wait_start(wait_event_info);
returnCode = fcntl(VfdCache[file].fd, F_RDADVISE, &ra);
pgstat_report_wait_end();
if (returnCode != -1)
return 0;
else
return errno;
}
#else #else
Assert(FileIsValid(file));
return 0; return 0;
#endif #endif
} }

View File

@ -139,9 +139,8 @@
/* /*
* USE_PREFETCH code should be compiled only if we have a way to implement * USE_PREFETCH code should be compiled only if we have a way to implement
* prefetching. (This is decoupled from USE_POSIX_FADVISE because there * prefetching. (This is decoupled from USE_POSIX_FADVISE because there
* might in future be support for alternative low-level prefetch APIs. * might in future be support for alternative low-level prefetch APIs,
* If you change this, you probably need to adjust the error message in * as well as platform-specific APIs defined elsewhere.)
* check_effective_io_concurrency.)
*/ */
#ifdef USE_POSIX_FADVISE #ifdef USE_POSIX_FADVISE
#define USE_PREFETCH #define USE_PREFETCH

View File

@ -6,3 +6,8 @@
#define HAVE_FSYNC_WRITETHROUGH #define HAVE_FSYNC_WRITETHROUGH
#endif #endif
/*
* macOS has a platform-specific implementation of prefetching.
*/
#define USE_PREFETCH