diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 8837f83..c87fd47 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -162,6 +162,14 @@ static const struct #define ConditionalLockTupleTuplock(rel, tup, mode) \ ConditionalLockTuple((rel), (tup), tupleLockExtraInfo[mode].hwlock) +#ifdef USE_PREFETCH +typedef struct +{ + int next_item; + BlockNumber cur_hblkno; +} PrefetchState; +#endif + /* * This table maps tuple lock strength values for each particular * MultiXactStatus value. @@ -6990,6 +6998,45 @@ HeapTupleHeaderAdvanceLatestRemovedXid(HeapTupleHeader tuple, /* *latestRemovedXid may still be invalid at end */ } +#ifdef USE_PREFETCH +/* + * prefetch_buffer + * + * Pre-fetch 'prefetch_count' numnber of buffers. + * Continues to scan the tids array from the last position that was scanned + * for previous pre-fetching. + */ +static void +prefetch_buffer(Relation rel, PrefetchState *prefetch_state, + ItemPointerData *tids, int nitems, int prefetch_count) +{ + int count = 0; + BlockNumber hblkno = prefetch_state->cur_hblkno; + int i; + + for (i = prefetch_state->next_item; i < nitems && count < prefetch_count; i++) + { + ItemPointer htid = &tids[i]; + + if (hblkno == InvalidBlockNumber || + ItemPointerGetBlockNumber(htid) != hblkno) + { + hblkno = ItemPointerGetBlockNumber(htid); + + count++; + PrefetchBuffer(rel, MAIN_FORKNUM, hblkno); + } + } + + /* + * Keep track of the item pointer array position, so that next time we can + * continue from this position. + */ + prefetch_state->next_item = i; + prefetch_state->cur_hblkno = hblkno; +} +#endif + /* * Get the latestRemovedXid from the heap pages pointed at by the index * tuples being deleted. @@ -7011,6 +7058,7 @@ heap_compute_xid_horizon_for_tuples(Relation rel, BlockNumber hblkno; Buffer buf = InvalidBuffer; Page hpage; + PrefetchState prefetch_state; /* * Sort to avoid repeated lookups for the same page, and to make it more @@ -7023,19 +7071,10 @@ heap_compute_xid_horizon_for_tuples(Relation rel, /* prefetch all pages */ #ifdef USE_PREFETCH - hblkno = InvalidBlockNumber; - for (int i = 0; i < nitems; i++) - { - ItemPointer htid = &tids[i]; - - if (hblkno == InvalidBlockNumber || - ItemPointerGetBlockNumber(htid) != hblkno) - { - hblkno = ItemPointerGetBlockNumber(htid); - - PrefetchBuffer(rel, MAIN_FORKNUM, hblkno); - } - } + prefetch_state.next_item = 0; + prefetch_state.cur_hblkno = InvalidBlockNumber; + prefetch_buffer(rel, &prefetch_state, tids, nitems, + 5 /* prefetch distance ; TODO: use effective_io_concurrency */); #endif /* Iterate over all tids, and check their horizon */ @@ -7063,6 +7102,13 @@ heap_compute_xid_horizon_for_tuples(Relation rel, hblkno = ItemPointerGetBlockNumber(htid); buf = ReadBuffer(rel, hblkno); + + /* + * Need to maintain the prefetch distance, so prefetch a page each + * time we read a new page. + */ + prefetch_buffer(rel, &prefetch_state, tids, nitems, 1); + hpage = BufferGetPage(buf); LockBuffer(buf, BUFFER_LOCK_SHARE);