size_t size;
int16 queue_size;
int16 max_ios;
+ int strategy_pin_limit;
uint32 max_pinned_buffers;
Oid tablespace_id;
SMgrRelation smgr;
max_pinned_buffers = Min(max_pinned_buffers,
PG_INT16_MAX - io_combine_limit - 1);
+ /* Give the strategy a chance to limit the number of buffers we pin. */
+ strategy_pin_limit = GetAccessStrategyPinLimit(strategy);
+ max_pinned_buffers = Min(strategy_pin_limit, max_pinned_buffers);
+
/* Don't allow this backend to pin more than its share of buffers. */
if (SmgrIsTemp(smgr))
LimitAdditionalLocalPins(&max_pinned_buffers);
return strategy->nbuffers;
}
+/*
+ * GetAccessStrategyPinLimit -- get cap of number of buffers that should be pinned
+ *
+ * When pinning extra buffers to look ahead, users of a ring-based strategy are
+ * in danger of pinning too much of the ring at once while performing look-ahead.
+ * For some strategies, that means "escaping" from the ring, and in others it
+ * means forcing dirty data to disk very frequently with associated WAL
+ * flushing. Since external code has no insight into any of that, allow
+ * individual strategy types to expose a clamp that should be applied when
+ * deciding on a maximum number of buffers to pin at once.
+ *
+ * Callers should combine this number with other relevant limits and take the
+ * minimum.
+ */
+int
+GetAccessStrategyPinLimit(BufferAccessStrategy strategy)
+{
+ if (strategy == NULL)
+ return NBuffers;
+
+ switch (strategy->btype)
+ {
+ case BAS_BULKREAD:
+
+ /*
+ * Since BAS_BULKREAD uses StrategyRejectBuffer(), dirty buffers
+ * shouldn't be a problem and the caller is free to pin up to the
+ * entire ring at once.
+ */
+ return strategy->nbuffers;
+
+ default:
+
+ /*
+ * Tell caller not to pin more than half the buffers in the ring.
+ * This is a trade-off between look ahead distance and deferring
+ * writeback and associated WAL traffic.
+ */
+ return strategy->nbuffers / 2;
+ }
+}
+
/*
* FreeAccessStrategy -- release a BufferAccessStrategy object
*
extern BufferAccessStrategy GetAccessStrategyWithSize(BufferAccessStrategyType btype,
int ring_size_kb);
extern int GetAccessStrategyBufferCount(BufferAccessStrategy strategy);
+extern int GetAccessStrategyPinLimit(BufferAccessStrategy strategy);
extern void FreeAccessStrategy(BufferAccessStrategy strategy);