From 8a1fec02cdeb2d26c8ebae9a7662fdde7068bc93 Mon Sep 17 00:00:00 2001 From: Tomas Vondra Date: Tue, 2 Apr 2024 17:50:58 +0200 Subject: [PATCH v20240405 3/3] Try prefetching larger chunks of data from the same file Similarly to performing copy/read/write in larger chunks, it may be beneficial to do the same for posix_fadvise. There's a caveat - this depends on seeing sufficiently larger chunks of blocks in the prefetch method, which depends on the copy batch. Once the distance stops growing, the prefetch window will be the same as the copy batch. If we copy 8 blocks, the prefetch will also see 8 new blocks. If we copy 128 blocks, prefetch will also see 128 new blocks. And so on. --- src/bin/pg_combinebackup/reconstruct.c | 38 ++++++++++++++++++++------ 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/bin/pg_combinebackup/reconstruct.c b/src/bin/pg_combinebackup/reconstruct.c index dd7a8841a55..155493c52f4 100644 --- a/src/bin/pg_combinebackup/reconstruct.c +++ b/src/bin/pg_combinebackup/reconstruct.c @@ -77,7 +77,8 @@ typedef struct prefetch_state int prefetch_distance; /* current distance (<= target) */ int prefetch_target; /* target distance */ - /* prefetch statistics - number of prefetched blocks */ + /* prefetch statistics - number of requests and prefetched blocks */ + unsigned prefetch_count; unsigned prefetch_blocks; } prefetch_state; @@ -779,8 +780,8 @@ write_reconstructed_file(char *input_filename, if (prefetch.prefetch_blocks > 0) { /* print how many blocks we prefetched / skipped */ - pg_log_debug("prefetch blocks %u (%u skipped)", - prefetch.prefetch_blocks, + pg_log_debug("prefetch requests %u blocks %u (%u skipped)", + prefetch.prefetch_count, prefetch.prefetch_blocks, (block_length - prefetch.prefetch_blocks)); } @@ -852,8 +853,13 @@ prefetch_init(prefetch_state *state, int prefetch_target) Assert(prefetch_target >= 0); state->next_block = 0; - state->prefetch_distance = 0; + + /* XXX Disables the gradual ramp-up, but we're reading data in batches and + * we probably need to cover the whole next batch at once. */ + state->prefetch_distance = prefetch_target; state->prefetch_target = prefetch_target; + + state->prefetch_count = 0; state->prefetch_blocks = 0; } @@ -876,6 +882,7 @@ prefetch_blocks(prefetch_state *state, unsigned current_block, unsigned block_length, rfile **sourcemap, off_t* offsetmap) { #ifdef USE_PREFETCH + /* end of prefetch range (first block to not prefetch) */ unsigned max_block; /* bail out if prefetching not enabled */ @@ -911,18 +918,31 @@ prefetch_blocks(prefetch_state *state, unsigned current_block, while (state->next_block < max_block) { - rfile *f = sourcemap[state->next_block]; - off_t off = offsetmap[state->next_block]; + /* range to prefetch in this round */ + int nblocks = 0; + unsigned block = state->next_block; + + rfile *f = sourcemap[block]; + off_t off = offsetmap[block]; + + /* find the last block in this prefetch range */ + while ((block + nblocks < max_block) && + (sourcemap[block + nblocks] == f)) + nblocks++; + + Assert(nblocks <= state->prefetch_distance); - state->next_block++; + /* remember how far we prefetched, even for f=NULL */ + state->next_block = block + nblocks; if (f == NULL) continue; - state->prefetch_blocks += 1; + state->prefetch_blocks += nblocks; + state->prefetch_count += 1; /* We ignore errors because this is only a hint.*/ - (void) posix_fadvise(f->fd, off, BLCKSZ, POSIX_FADV_WILLNEED); + (void) posix_fadvise(f->fd, off, (nblocks * BLCKSZ), POSIX_FADV_WILLNEED); } Assert(state->next_block <= block_length); -- 2.44.0