@ -211,6 +211,8 @@ static int32 PrivateRefCountOverflowed = 0;
static uint32 PrivateRefCountClock = 0 ;
static uint32 PrivateRefCountClock = 0 ;
static PrivateRefCountEntry * ReservedRefCountEntry = NULL ;
static PrivateRefCountEntry * ReservedRefCountEntry = NULL ;
static uint32 MaxProportionalPins ;
static void ReservePrivateRefCountEntry ( void ) ;
static void ReservePrivateRefCountEntry ( void ) ;
static PrivateRefCountEntry * NewPrivateRefCountEntry ( Buffer buffer ) ;
static PrivateRefCountEntry * NewPrivateRefCountEntry ( Buffer buffer ) ;
static PrivateRefCountEntry * GetPrivateRefCountEntry ( Buffer buffer , bool do_move ) ;
static PrivateRefCountEntry * GetPrivateRefCountEntry ( Buffer buffer , bool do_move ) ;
@ -2097,43 +2099,62 @@ again:
return buf ;
return buf ;
}
}
/*
* Return the maximum number of buffers that a backend should try to pin once ,
* to avoid exceeding its fair share . This is the highest value that
* GetAdditionalPinLimit ( ) could ever return . Note that it may be zero on a
* system with a very small buffer pool relative to max_connections .
*/
uint32
GetPinLimit ( void )
{
return MaxProportionalPins ;
}
/*
* Return the maximum number of additional buffers that this backend should
* pin if it wants to stay under the per - backend limit , considering the number
* of buffers it has already pinned . Unlike LimitAdditionalPins ( ) , the limit
* return by this function can be zero .
*/
uint32
GetAdditionalPinLimit ( void )
{
uint32 estimated_pins_held ;
/*
* We get the number of " overflowed " pins for free , but don ' t know the
* number of pins in PrivateRefCountArray . The cost of calculating that
* exactly doesn ' t seem worth it , so just assume the max .
*/
estimated_pins_held = PrivateRefCountOverflowed + REFCOUNT_ARRAY_ENTRIES ;
/* Is this backend already holding more than its fair share? */
if ( estimated_pins_held > MaxProportionalPins )
return 0 ;
return MaxProportionalPins - estimated_pins_held ;
}
/*
/*
* Limit the number of pins a batch operation may additionally acquire , to
* Limit the number of pins a batch operation may additionally acquire , to
* avoid running out of pinnable buffers .
* avoid running out of pinnable buffers .
*
*
* One additional pin is always allowed , as otherwise the operation likely
* One additional pin is always allowed , on the assumption that the operation
* cannot be performed at all .
* requires at least one to make progress .
*
* The number of allowed pins for a backend is computed based on
* shared_buffers and the maximum number of connections possible . That ' s very
* pessimistic , but outside of toy - sized shared_buffers it should allow
* sufficient pins .
*/
*/
void
void
LimitAdditionalPins ( uint32 * additional_pins )
LimitAdditionalPins ( uint32 * additional_pins )
{
{
uint32 max_backends ;
uint32 limit ;
int max_proportional_pins ;
if ( * additional_pins < = 1 )
if ( * additional_pins < = 1 )
return ;
return ;
max_backends = MaxBackends + NUM_AUXILIARY_PROCS ;
limit = GetAdditionalPinLimit ( ) ;
max_proportional_pins = NBuffers / max_backends ;
limit = Max ( limit , 1 ) ;
if ( limit < * additional_pins )
/*
* additional_pins = limit ;
* Subtract the approximate number of buffers already pinned by this
* backend . We get the number of " overflowed " pins for free , but don ' t
* know the number of pins in PrivateRefCountArray . The cost of
* calculating that exactly doesn ' t seem worth it , so just assume the max .
*/
max_proportional_pins - = PrivateRefCountOverflowed + REFCOUNT_ARRAY_ENTRIES ;
if ( max_proportional_pins < = 0 )
max_proportional_pins = 1 ;
if ( * additional_pins > max_proportional_pins )
* additional_pins = max_proportional_pins ;
}
}
/*
/*
@ -3575,6 +3596,15 @@ InitBufferManagerAccess(void)
{
{
HASHCTL hash_ctl ;
HASHCTL hash_ctl ;
/*
* An advisory limit on the number of pins each backend should hold , based
* on shared_buffers and the maximum number of connections possible .
* That ' s very pessimistic , but outside toy - sized shared_buffers it should
* allow plenty of pins . LimitAdditionalPins ( ) and
* GetAdditionalPinLimit ( ) can be used to check the remaining balance .
*/
MaxProportionalPins = NBuffers / ( MaxBackends + NUM_AUXILIARY_PROCS ) ;
memset ( & PrivateRefCountArray , 0 , sizeof ( PrivateRefCountArray ) ) ;
memset ( & PrivateRefCountArray , 0 , sizeof ( PrivateRefCountArray ) ) ;
hash_ctl . keysize = sizeof ( int32 ) ;
hash_ctl . keysize = sizeof ( int32 ) ;