@@ -150,6 +150,8 @@ BitmapHeapNext(BitmapHeapScanState *node)
150
150
*/
151
151
pstate -> tbmiterator = tbm_prepare_shared_iterate (tbm );
152
152
#ifdef USE_PREFETCH
153
+ node -> n_prefetch_requests = 0 ;
154
+ node -> prefetch_request_pos = 0 ;
153
155
if (node -> prefetch_maximum > 0 )
154
156
{
155
157
pstate -> prefetch_iterator =
@@ -173,13 +175,6 @@ BitmapHeapNext(BitmapHeapScanState *node)
173
175
tbm_attach_shared_iterate (dsa , pstate -> tbmiterator );
174
176
node -> tbmres = tbmres = NULL ;
175
177
176
- #ifdef USE_PREFETCH
177
- if (node -> prefetch_maximum > 0 )
178
- {
179
- node -> shared_prefetch_iterator =
180
- tbm_attach_shared_iterate (dsa , pstate -> prefetch_iterator );
181
- }
182
- #endif /* USE_PREFETCH */
183
178
}
184
179
node -> initialized = true;
185
180
}
@@ -198,15 +193,24 @@ BitmapHeapNext(BitmapHeapScanState *node)
198
193
if (!pstate )
199
194
node -> tbmres = tbmres = tbm_iterate (tbmiterator );
200
195
else
201
- node -> tbmres = tbmres = tbm_shared_iterate (shared_tbmiterator );
196
+ {
197
+ if (node -> n_prefetch_requests != 0 )
198
+ {
199
+ node -> tbmres = tbmres = (TBMIterateResult * )& node -> prefetch_requests [node -> prefetch_request_pos ];
200
+ node -> n_prefetch_requests -= 1 ;
201
+ node -> prefetch_request_pos = (node -> prefetch_request_pos + 1 ) % MAX_IO_CONCURRENCY ;
202
+ if (node -> prefetch_pages != 0 )
203
+ node -> prefetch_pages -= 1 ;
204
+ }
205
+ else
206
+ node -> tbmres = tbmres = tbm_shared_iterate (shared_tbmiterator );
207
+ }
202
208
if (tbmres == NULL )
203
209
{
204
210
/* no more entries in the bitmap */
205
211
break ;
206
212
}
207
213
208
- BitmapAdjustPrefetchIterator (node , tbmres );
209
-
210
214
/*
211
215
* We can skip fetching the heap page if we don't need any fields
212
216
* from the heap, and the bitmap entries don't need rechecking,
@@ -361,54 +365,21 @@ BitmapAdjustPrefetchIterator(BitmapHeapScanState *node,
361
365
TBMIterateResult * tbmres )
362
366
{
363
367
#ifdef USE_PREFETCH
364
- ParallelBitmapHeapState * pstate = node -> pstate ;
368
+ TBMIterator * prefetch_iterator = node -> prefetch_iterator ;
369
+ Assert (node -> pstate == NULL );
365
370
366
- if (pstate == NULL )
371
+ if (node -> prefetch_pages > 0 )
367
372
{
368
- TBMIterator * prefetch_iterator = node -> prefetch_iterator ;
369
-
370
- if (node -> prefetch_pages > 0 )
371
- {
372
- /* The main iterator has closed the distance by one page */
373
- node -> prefetch_pages -- ;
374
- }
375
- else if (prefetch_iterator )
376
- {
377
- /* Do not let the prefetch iterator get behind the main one */
378
- TBMIterateResult * tbmpre = tbm_iterate (prefetch_iterator );
379
-
380
- if (tbmpre == NULL || tbmpre -> blockno != tbmres -> blockno )
381
- elog (ERROR , "prefetch and main iterators are out of sync" );
382
- }
383
- return ;
373
+ /* The main iterator has closed the distance by one page */
374
+ node -> prefetch_pages -- ;
384
375
}
385
-
386
- if (node -> prefetch_maximum > 0 )
376
+ else if (prefetch_iterator )
387
377
{
388
- TBMSharedIterator * prefetch_iterator = node -> shared_prefetch_iterator ;
378
+ /* Do not let the prefetch iterator get behind the main one */
379
+ TBMIterateResult * tbmpre = tbm_iterate (prefetch_iterator );
389
380
390
- SpinLockAcquire (& pstate -> mutex );
391
- if (pstate -> prefetch_pages > 0 )
392
- {
393
- pstate -> prefetch_pages -- ;
394
- SpinLockRelease (& pstate -> mutex );
395
- }
396
- else
397
- {
398
- /* Release the mutex before iterating */
399
- SpinLockRelease (& pstate -> mutex );
400
-
401
- /*
402
- * In case of shared mode, we can not ensure that the current
403
- * blockno of the main iterator and that of the prefetch iterator
404
- * are same. It's possible that whatever blockno we are
405
- * prefetching will be processed by another process. Therefore,
406
- * we don't validate the blockno here as we do in non-parallel
407
- * case.
408
- */
409
- if (prefetch_iterator )
410
- tbm_shared_iterate (prefetch_iterator );
411
- }
381
+ if (tbmpre == NULL || tbmpre -> blockno != tbmres -> blockno )
382
+ elog (ERROR , "prefetch and main iterators are out of sync" );
412
383
}
413
384
#endif /* USE_PREFETCH */
414
385
}
@@ -425,35 +396,14 @@ static inline void
425
396
BitmapAdjustPrefetchTarget (BitmapHeapScanState * node )
426
397
{
427
398
#ifdef USE_PREFETCH
428
- ParallelBitmapHeapState * pstate = node -> pstate ;
429
-
430
- if (pstate == NULL )
431
- {
432
- if (node -> prefetch_target >= node -> prefetch_maximum )
433
- /* don't increase any further */ ;
434
- else if (node -> prefetch_target >= node -> prefetch_maximum / 2 )
435
- node -> prefetch_target = node -> prefetch_maximum ;
436
- else if (node -> prefetch_target > 0 )
437
- node -> prefetch_target *= 2 ;
438
- else
439
- node -> prefetch_target ++ ;
440
- return ;
441
- }
442
-
443
- /* Do an unlocked check first to save spinlock acquisitions. */
444
- if (pstate -> prefetch_target < node -> prefetch_maximum )
445
- {
446
- SpinLockAcquire (& pstate -> mutex );
447
- if (pstate -> prefetch_target >= node -> prefetch_maximum )
448
- /* don't increase any further */ ;
449
- else if (pstate -> prefetch_target >= node -> prefetch_maximum / 2 )
450
- pstate -> prefetch_target = node -> prefetch_maximum ;
451
- else if (pstate -> prefetch_target > 0 )
452
- pstate -> prefetch_target *= 2 ;
453
- else
454
- pstate -> prefetch_target ++ ;
455
- SpinLockRelease (& pstate -> mutex );
456
- }
399
+ if (node -> prefetch_target >= node -> prefetch_maximum )
400
+ /* don't increase any further */ ;
401
+ else if (node -> prefetch_target >= node -> prefetch_maximum / 2 )
402
+ node -> prefetch_target = node -> prefetch_maximum ;
403
+ else if (node -> prefetch_target > 0 )
404
+ node -> prefetch_target *= 2 ;
405
+ else
406
+ node -> prefetch_target ++ ;
457
407
#endif /* USE_PREFETCH */
458
408
}
459
409
@@ -507,56 +457,46 @@ BitmapPrefetch(BitmapHeapScanState *node, TableScanDesc scan)
507
457
PrefetchBuffer (scan -> rs_rd , MAIN_FORKNUM , tbmpre -> blockno );
508
458
}
509
459
}
510
-
511
- return ;
512
460
}
513
-
514
- if (pstate -> prefetch_pages < pstate -> prefetch_target )
461
+ else
515
462
{
516
- TBMSharedIterator * prefetch_iterator = node -> shared_prefetch_iterator ;
517
-
518
- if (prefetch_iterator )
463
+ while (1 )
519
464
{
520
- while (1 )
521
- {
522
- TBMIterateResult * tbmpre ;
523
- bool do_prefetch = false;
524
- bool skip_fetch ;
465
+ TBMIterateResult * tbmpre ;
466
+ bool do_prefetch = false;
467
+ bool skip_fetch ;
525
468
526
- /*
527
- * Recheck under the mutex. If some other process has already
528
- * done enough prefetching then we need not to do anything.
529
- */
530
- SpinLockAcquire (& pstate -> mutex );
531
- if (pstate -> prefetch_pages < pstate -> prefetch_target )
532
- {
533
- pstate -> prefetch_pages ++ ;
534
- do_prefetch = true;
535
- }
536
- SpinLockRelease (& pstate -> mutex );
469
+ if (node -> prefetch_pages < node -> prefetch_target )
470
+ {
471
+ Assert (node -> n_prefetch_requests < MAX_IO_CONCURRENCY );
472
+ node -> prefetch_pages ++ ;
473
+ do_prefetch = true;
474
+ }
537
475
538
- if (!do_prefetch )
539
- return ;
476
+ if (!do_prefetch )
477
+ return ;
540
478
541
- tbmpre = tbm_shared_iterate (prefetch_iterator );
542
- if (tbmpre == NULL )
543
- {
544
- /* No more pages to prefetch */
545
- tbm_end_shared_iterate (prefetch_iterator );
546
- node -> shared_prefetch_iterator = NULL ;
547
- break ;
548
- }
479
+ tbmpre = tbm_shared_iterate (node -> shared_tbmiterator );
480
+ if (tbmpre != NULL )
481
+ {
482
+ memcpy (& node -> prefetch_requests [(node -> prefetch_request_pos + node -> n_prefetch_requests ) % MAX_IO_CONCURRENCY ], tbmpre , sizeof (TBMIteratePrefetchResult ));
483
+ node -> n_prefetch_requests += 1 ;
484
+ }
485
+ else
486
+ {
487
+ /* No more pages to prefetch */
488
+ break ;
489
+ }
549
490
550
- /* As above, skip prefetch if we expect not to need page */
551
- skip_fetch = (node -> can_skip_fetch &&
552
- (node -> tbmres ? !node -> tbmres -> recheck : false) &&
553
- VM_ALL_VISIBLE (node -> ss .ss_currentRelation ,
554
- tbmpre -> blockno ,
555
- & node -> pvmbuffer ));
491
+ /* As above, skip prefetch if we expect not to need page */
492
+ skip_fetch = (node -> can_skip_fetch &&
493
+ (node -> tbmres ? !node -> tbmres -> recheck : false) &&
494
+ VM_ALL_VISIBLE (node -> ss .ss_currentRelation ,
495
+ tbmpre -> blockno ,
496
+ & node -> pvmbuffer ));
556
497
557
- if (!skip_fetch )
558
- PrefetchBuffer (scan -> rs_rd , MAIN_FORKNUM , tbmpre -> blockno );
559
- }
498
+ if (!skip_fetch )
499
+ PrefetchBuffer (scan -> rs_rd , MAIN_FORKNUM , tbmpre -> blockno );
560
500
}
561
501
}
562
502
#endif /* USE_PREFETCH */
@@ -613,8 +553,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
613
553
tbm_end_iterate (node -> prefetch_iterator );
614
554
if (node -> shared_tbmiterator )
615
555
tbm_end_shared_iterate (node -> shared_tbmiterator );
616
- if (node -> shared_prefetch_iterator )
617
- tbm_end_shared_iterate (node -> shared_prefetch_iterator );
618
556
if (node -> tbm )
619
557
tbm_free (node -> tbm );
620
558
if (node -> vmbuffer != InvalidBuffer )
@@ -627,7 +565,6 @@ ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
627
565
node -> prefetch_iterator = NULL ;
628
566
node -> initialized = false;
629
567
node -> shared_tbmiterator = NULL ;
630
- node -> shared_prefetch_iterator = NULL ;
631
568
node -> vmbuffer = InvalidBuffer ;
632
569
node -> pvmbuffer = InvalidBuffer ;
633
570
@@ -683,8 +620,6 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
683
620
tbm_free (node -> tbm );
684
621
if (node -> shared_tbmiterator )
685
622
tbm_end_shared_iterate (node -> shared_tbmiterator );
686
- if (node -> shared_prefetch_iterator )
687
- tbm_end_shared_iterate (node -> shared_prefetch_iterator );
688
623
if (node -> vmbuffer != InvalidBuffer )
689
624
ReleaseBuffer (node -> vmbuffer );
690
625
if (node -> pvmbuffer != InvalidBuffer )
@@ -739,7 +674,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
739
674
scanstate -> pscan_len = 0 ;
740
675
scanstate -> initialized = false;
741
676
scanstate -> shared_tbmiterator = NULL ;
742
- scanstate -> shared_prefetch_iterator = NULL ;
743
677
scanstate -> pstate = NULL ;
744
678
745
679
/*
0 commit comments