Skip to content

Commit 5a560e3

Browse files
knizhniktristan957
authored andcommitted
Heap bitmap scan prefetch fix2 v14 (#275)
* Copy iterator result in BitmapHeapNext * Restore initial -1 value for prefetch_target * Add tbmres_copy to BitmapHeapScanState
1 parent 1386eb5 commit 5a560e3

File tree

2 files changed

+27
-27
lines changed

2 files changed

+27
-27
lines changed

src/backend/executor/nodeBitmapHeapscan.c

+25-25
Original file line numberDiff line numberDiff line change
@@ -149,19 +149,15 @@ BitmapHeapNext(BitmapHeapScanState *node)
149149
* multiple processes to iterate jointly.
150150
*/
151151
pstate->tbmiterator = tbm_prepare_shared_iterate(tbm);
152-
#ifdef USE_PREFETCH
153-
node->n_prefetch_requests = 0;
154-
node->prefetch_request_pos = 0;
155-
if (node->prefetch_maximum > 0)
156-
{
157-
node->prefetch_pages = 0;
158-
node->prefetch_target = -1;
159-
}
160-
#endif
161152

162153
/* We have initialized the shared state so wake up others. */
163154
BitmapDoneInitializingSharedState(pstate);
164155
}
156+
#ifdef USE_PREFETCH
157+
node->prefetch_head = 0;
158+
node->prefetch_pages = 0;
159+
node->prefetch_target = -1;
160+
#endif
165161

166162
/* Allocate a private iterator and attach the shared state to it */
167163
node->shared_tbmiterator = shared_tbmiterator =
@@ -184,20 +180,25 @@ BitmapHeapNext(BitmapHeapScanState *node)
184180
if (tbmres == NULL)
185181
{
186182
if (!pstate)
187-
node->tbmres = tbmres = tbm_iterate(tbmiterator);
183+
tbmres = tbm_iterate(tbmiterator);
188184
else
189185
{
190-
if (node->n_prefetch_requests != 0)
186+
if (node->prefetch_pages != 0)
191187
{
192-
node->tbmres = tbmres = (TBMIterateResult *)&node->prefetch_requests[node->prefetch_request_pos];
193-
node->n_prefetch_requests -= 1;
194-
node->prefetch_request_pos = (node->prefetch_request_pos + 1) % MAX_IO_CONCURRENCY;
195-
if (node->prefetch_pages != 0)
196-
node->prefetch_pages -= 1;
188+
tbmres = (TBMIterateResult *)&node->prefetch_requests[node->prefetch_head];
189+
node->prefetch_pages -= 1;
190+
node->prefetch_head = (node->prefetch_head + 1) % MAX_IO_CONCURRENCY;
197191
}
198192
else
199-
node->tbmres = tbmres = tbm_shared_iterate(shared_tbmiterator);
193+
tbmres = tbm_shared_iterate(shared_tbmiterator);
194+
if (tbmres)
195+
{
196+
/* Need to copy result because iterator can be used for prefetch and vocant position in prefetch ring buffer can also be reused */
197+
memcpy(&node->tbmres_copy, tbmres, offsetof(TBMIterateResult, offsets) + sizeof(OffsetNumber)*Max(tbmres->ntuples, 0));
198+
tbmres = (TBMIterateResult *)&node->tbmres_copy;
199+
}
200200
}
201+
node->tbmres = tbmres;
201202
if (tbmres == NULL)
202203
{
203204
/* no more entries in the bitmap */
@@ -236,7 +237,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
236237
/* AM doesn't think this block is valid, skip */
237238
continue;
238239
}
239-
240240
if (tbmres->ntuples >= 0)
241241
node->exact_pages++;
242242
else
@@ -455,8 +455,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
455455

456456
if (node->prefetch_pages < node->prefetch_target)
457457
{
458-
Assert(node->n_prefetch_requests < MAX_IO_CONCURRENCY);
459-
node->prefetch_pages++;
458+
Assert(node->prefetch_pages < MAX_IO_CONCURRENCY);
460459
do_prefetch = true;
461460
}
462461

@@ -466,8 +465,10 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
466465
tbmpre = tbm_shared_iterate(node->shared_tbmiterator);
467466
if (tbmpre != NULL)
468467
{
469-
memcpy(&node->prefetch_requests[(node->prefetch_request_pos + node->n_prefetch_requests) % MAX_IO_CONCURRENCY], tbmpre, sizeof(TBMIteratePrefetchResult));
470-
node->n_prefetch_requests += 1;
468+
memcpy(&node->prefetch_requests[(node->prefetch_head + node->prefetch_pages) % MAX_IO_CONCURRENCY],
469+
tbmpre,
470+
offsetof(TBMIterateResult, offsets) + sizeof(OffsetNumber)*Max(tbmpre->ntuples, 0));
471+
node->prefetch_pages += 1;
471472
}
472473
else
473474
{
@@ -477,7 +478,7 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
477478

478479
/* As above, skip prefetch if we expect not to need page */
479480
skip_fetch = (node->can_skip_fetch &&
480-
(node->tbmres ? !node->tbmres->recheck : false) &&
481+
!tbmpre->recheck &&
481482
VM_ALL_VISIBLE(node->ss.ss_currentRelation,
482483
tbmpre->blockno,
483484
&node->pvmbuffer));
@@ -715,8 +716,7 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
715716
* Maximum number of prefetches for the tablespace if configured,
716717
* otherwise the current value of the effective_io_concurrency GUC.
717718
*/
718-
scanstate->prefetch_maximum =
719-
get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
719+
scanstate->prefetch_maximum = get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace);
720720

721721
scanstate->ss.ss_currentRelation = currentRelation;
722722

src/include/nodes/execnodes.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -1699,8 +1699,8 @@ typedef struct BitmapHeapScanState
16991699
TBMSharedIterator *shared_tbmiterator;
17001700
/* parallel worker private ring buffer with prefetch requests: it allows to access prefetch result from the same worker */
17011701
TBMIteratePrefetchResult prefetch_requests[MAX_IO_CONCURRENCY];
1702-
int n_prefetch_requests; /* number of used elements in prefetch_requests ring buffer */
1703-
int prefetch_request_pos; /* head position in ring buffer */
1702+
TBMIteratePrefetchResult tbmres_copy; /* copy of current iterator result */
1703+
int prefetch_head; /* head position in ring buffer */
17041704
ParallelBitmapHeapState *pstate;
17051705
} BitmapHeapScanState;
17061706

0 commit comments

Comments
 (0)