Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 15f0cb2

Browse files
committed
Increase BAS_BULKREAD based on effective_io_concurrency
Before, BAS_BULKREAD was always of size 256kB. With the default io_combine_limit of 16, that only allowed 1-2 IOs to be in flight - insufficient even on very low latency storage. We don't just want to increase the size to a much larger hardcoded value, as very large rings (10s of MBs of of buffers), appear to have negative performance effects when reading in data that the OS has cached (but not when actually needing to do IO). To address this, increase the size of BAS_BULKREAD to allow for io_combine_limit * effective_io_concurrency buffers getting read in. To prevent the ring being much larger than useful, limit the increased size with GetPinLimit(). The formula outlined above keeps the ring size to sizes for which we have not observed performance regressions, unless very large effective_io_concurrency values are used together with large shared_buffers setting. Reviewed-by: Thomas Munro <thomas.munro@gmail.com> Discussion: https://postgr.es/m/lqwghabtu2ak4wknzycufqjm5ijnxhb4k73vzphlt2a3wsemcd@gtftg44kdim6 Discussion: https://postgr.es/m/uvrtrknj4kdytuboidbhwclo4gxhswwcpgadptsjvjqcluzmah@brqs62irg4dt
1 parent dcf7e16 commit 15f0cb2

File tree

1 file changed

+44
-2
lines changed

1 file changed

+44
-2
lines changed

src/backend/storage/buffer/freelist.c

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,8 +555,50 @@ GetAccessStrategy(BufferAccessStrategyType btype)
555555
return NULL;
556556

557557
case BAS_BULKREAD:
558-
ring_size_kb = 256;
559-
break;
558+
{
559+
int ring_max_kb;
560+
561+
/*
562+
* The ring always needs to be large enough to allow some
563+
* separation in time between providing a buffer to the user
564+
* of the strategy and that buffer being reused. Otherwise the
565+
* user's pin will prevent reuse of the buffer, even without
566+
* concurrent activity.
567+
*
568+
* We also need to ensure the ring always is large enough for
569+
* SYNC_SCAN_REPORT_INTERVAL, as noted above.
570+
*
571+
* Thus we start out a minimal size and increase the size
572+
* further if appropriate.
573+
*/
574+
ring_size_kb = 256;
575+
576+
/*
577+
* There's no point in a larger ring if we won't be allowed to
578+
* pin sufficiently many buffers. But we never limit to less
579+
* than the minimal size above.
580+
*/
581+
ring_max_kb = GetPinLimit() * (BLCKSZ / 1024);
582+
ring_max_kb = Max(ring_size_kb, ring_max_kb);
583+
584+
/*
585+
* We would like the ring to additionally have space for the
586+
* the configured degree of IO concurrency. While being read
587+
* in, buffers can obviously not yet be reused.
588+
*
589+
* Each IO can be up to io_combine_limit blocks large, and we
590+
* want to start up to effective_io_concurrency IOs.
591+
*
592+
* Note that effective_io_concurrency may be 0, which disables
593+
* AIO.
594+
*/
595+
ring_size_kb += (BLCKSZ / 1024) *
596+
io_combine_limit * effective_io_concurrency;
597+
598+
if (ring_size_kb > ring_max_kb)
599+
ring_size_kb = ring_max_kb;
600+
break;
601+
}
560602
case BAS_BULKWRITE:
561603
ring_size_kb = 16 * 1024;
562604
break;

0 commit comments

Comments
 (0)