This commit is contained in:
Cachuela 2023-10-05 22:29:04 +08:00
parent e87d746b45
commit 3f585e4d35
1 changed files with 89 additions and 54 deletions

View File

@ -85,7 +85,7 @@ static void perform_delay(StrategyDelayStatus *status)//这个函数的目的是
{
if (++(status->retry_times) > MAX_RETRY_TIMES &&
get_dirty_page_num() > g_instance.attr.attr_storage.NBuffers * NEED_DELAY_RETRY_GET_BUF) {
// 如果已经重试了最大<E69C80><E5A4A7><EFBFBD>数,并且脏页数量超过了阈值
// 如果已经重试了最大<E69C80><E5A4A7><EFBFBD><EFBFBD><EFBFBD>数,并且脏页数量超过了阈值
if (status->cur_delay_time == 0) {
// 如果当前延迟时间为0则初始化为最小延迟时间
@ -430,19 +430,30 @@ void StrategyNotifyBgWriter(int bgwproc_no)
* Note: for somewhat historical reasons, the buffer lookup hashtable size
* is also determined here.
*/
Size StrategyShmemSize(void)
/*
BufTableShmemSize
TOTAL_BUFFER_NUM
NUM_BUFFER_PARTITIONS
使 MAXALIGN
便
*/
Size StrategyShmemSize(void)
{
Size size = 0;
/* size of lookup hash table ... see comment in StrategyInitialize */
/* 计算查找哈希表的共享内存大小,详情见 StrategyInitialize 函数的注释 */
size = add_size(size, BufTableShmemSize(TOTAL_BUFFER_NUM + NUM_BUFFER_PARTITIONS));
/* size of the shared replacement strategy control block */
/* 计算共享替换策略控制块的大小,需要对齐到 MAXALIGN 大小 */
size = add_size(size, MAXALIGN(sizeof(BufferStrategyControl)));
return size;
}
}
/*
* StrategyInitialize -- initialize the buffer cache replacement
* strategy.
@ -450,49 +461,56 @@ Size StrategyShmemSize(void)
* Assumes: All of the buffers are already built into a linked list.
* Only called by postmaster and only during initialization.
*/
/*
InitBufTable
TOTAL_BUFFER_NUM + NUM_BUFFER_PARTITIONS
ShmemInitStruct t_thrd.storage_cxt.StrategyControl
PostgreSQL
*/
void StrategyInitialize(bool init)
{
bool found = false;
/*
* Initialize the shared buffer lookup hashtable.
*
*
* Since we can't tolerate running out of lookup table entries, we must be
* sure to specify an adequate table size here. The maximum steady-state
* usage is of course NBuffers entries, but BufferAlloc() tries to insert
* a new entry before deleting the old. In principle this could be
* happening in each partition concurrently, so we could need as many as
* NBuffers + NUM_BUFFER_PARTITIONS entries.
* 使
* NBuffers BufferAlloc()
* NBuffers + NUM_BUFFER_PARTITIONS
*/
InitBufTable(TOTAL_BUFFER_NUM + NUM_BUFFER_PARTITIONS);
/*
* Get or create the shared strategy control block
*
*/
t_thrd.storage_cxt.StrategyControl =
(BufferStrategyControl *)ShmemInitStruct("Buffer Strategy Status", sizeof(BufferStrategyControl), &found);
if (!found) {
/*
* Only done once, usually in postmaster
* postmaster
*/
Assert(init);
SpinLockInit(&t_thrd.storage_cxt.StrategyControl->buffer_strategy_lock);
/* Initialize the clock sweep pointer */
/* 初始化时钟扫描指针 */
pg_atomic_init_u32(&t_thrd.storage_cxt.StrategyControl->nextVictimBuffer, 0);
/* Clear statistics */
/* 清空统计信息 */
t_thrd.storage_cxt.StrategyControl->completePasses = 0;
pg_atomic_init_u32(&t_thrd.storage_cxt.StrategyControl->numBufferAllocs, 0);
/* No pending notification */
/* 没有挂起的通知 */
t_thrd.storage_cxt.StrategyControl->bgwprocno = -1;
} else {
Assert(!init);
}
}
const int MIN_REPAIR_FILE_SLOT_NUM = 32;
/* ----------------------------------------------------------------
* Backend-private buffer ring management
@ -503,20 +521,26 @@ const int MIN_REPAIR_FILE_SLOT_NUM = 32;
*
* The object is allocated in the current memory context.
*/
/*
访 btype ring_size
BufferAccessStrategy
访
访访
*/
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
{
BufferAccessStrategy strategy;
int ring_size;
/*
* Select ring size to use. See buffer/README for rationales.
* 使buffer/README中的原理说明
*
* Note: if you change the ring size for BAS_BULKREAD, see also
* SYNC_SCAN_REPORT_INTERVAL in access/heap/syncscan.c.
* BAS_BULKREAD的环大小access/heap/syncscan.c中的SYNC_SCAN_REPORT_INTERVAL
*/
switch (btype) {
case BAS_NORMAL:
/* if someone asks for NORMAL, just give 'em a "default" object */
/* 如果有人要求NORMAL只需给他们一个“默认”对象 */
return NULL;
case BAS_BULKREAD:
@ -535,22 +559,22 @@ BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
default:
ereport(ERROR, (errcode(ERRCODE_INVALID_OPERATION),
(errmsg("unrecognized buffer access strategy: %d", (int)btype))));
return NULL; /* keep compiler quiet */
return NULL; /* 保持编译器安静 */
}
/* If the shared buffers is too small, make sure ring size not equal zero. */
/* 如果共享缓冲区太小,请确保环大小不等于零。 */
ring_size = Max(ring_size, 4);
/* Make sure ring isn't an undue fraction of shared buffers */
/* 确保环不是共享缓冲区的过大比例 */
if (btype != BAS_BULKWRITE && btype != BAS_BULKREAD)
ring_size = Min(g_instance.attr.attr_storage.NBuffers / 8, ring_size);
else
ring_size = Min(g_instance.attr.attr_storage.NBuffers / 4, ring_size);
/* Allocate the object and initialize all elements to zeroes */
/* 分配对象并将所有元素初始化为零 */
strategy = (BufferAccessStrategy)palloc0(offsetof(BufferAccessStrategyData, buffers) + ring_size * sizeof(Buffer));
/* Set fields that don't start out zero */
/* 设置初始不为零的字段 */
strategy->btype = btype;
strategy->ring_size = ring_size;
strategy->flush_rate = Min(u_sess->attr.attr_storage.backwrite_quantity, ring_size);
@ -558,6 +582,7 @@ BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
return strategy;
}
/*
* FreeAccessStrategy -- release a BufferAccessStrategy object
*
@ -566,13 +591,14 @@ BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
*/
void FreeAccessStrategy(BufferAccessStrategy strategy)
{
/* don't crash if called on a "default" strategy */
/* 不要在“默认”策略上调用时崩溃 */
if (strategy != NULL) {
pfree(strategy);
strategy = NULL;
pfree(strategy); // 释放策略对象占用的内存
strategy = NULL; // 将策略对象指针设置为 NULL以避免引用已释放的内存
}
}
const int MAX_RETRY_RING_TIMES = 100;
const float MAX_RETRY_RING_PCT = 0.1;
/*
@ -581,15 +607,21 @@ const float MAX_RETRY_RING_PCT = 0.1;
*
* The bufhdr spin lock is held on the returned buffer.
*/
/*
使
*/
static BufferDesc *GetBufferFromRing(BufferAccessStrategy strategy, uint32 *buf_state)
{
BufferDesc *buf = NULL;
Buffer buf_num;
uint32 local_buf_state; /* to avoid repeated (de-)referencing */
uint16 retry_times = 0;
BufferDesc *buf = NULL; // 用于存储缓冲区描述符的指针
Buffer buf_num; // 用于存储缓冲区编号的变量
uint32 local_buf_state; // 用于存储缓冲区状态的变量,以避免重复引用
uint16 retry_times = 0; // 用于记录重试次数的变量
RETRY:
/* Advance to next ring slot */
/* 移动到下一个环形槽位 */
if (++strategy->current >= strategy->ring_size)
strategy->current = 0;
retry_times++;
@ -597,9 +629,9 @@ RETRY:
ADIO_RUN()
{
/*
* Flush out buffers asynchronously from behind the current slot.
* This is a kludge because the PageListBackWrite() is not strictly
* asynchronous and this function really shouldn't be doing the actual I/O.
*
* PageListBackWrite()
* I/O
*/
if (AioCompltrIsReady() &&
((strategy->btype == BAS_BULKWRITE) && (strategy->current % strategy->flush_rate == 0))) {
@ -625,9 +657,8 @@ RETRY:
ADIO_END();
/*
* If the slot hasn't been filled yet, tell the caller to allocate a new
* buffer with the normal allocation strategy. He will then fill this
* slot by calling AddBufferToRing with the new buffer.
* 使
* AddBufferToRing
*/
buf_num = strategy->buffers[strategy->current];
if (buf_num == InvalidBuffer) {
@ -636,13 +667,10 @@ RETRY:
}
/*
* If the buffer is pinned we cannot use it under any circumstances.
* 使
*
* If usage_count is 0 or 1 then the buffer is fair game (we expect 1,
* since our own previous usage of the ring element would have left it
* there, but it might've been decremented by clock sweep since then). A
* higher usage_count indicates someone else has touched the buffer, so we
* shouldn't re-use it.
* usage_count 0 1使 1使
* usage_count 访
*/
buf = GetBufferDescriptor(buf_num - 1);
if (pg_atomic_read_u32(&buf->state) & (BM_DIRTY | BM_IS_META)) {
@ -666,13 +694,14 @@ RETRY:
UnlockBufHdr(buf, local_buf_state);
/*
* Tell caller to allocate a new buffer with the normal allocation
* strategy. He'll then replace this ring element via AddBufferToRing.
* 使
* AddBufferToRing
*/
strategy->current_was_in_ring = false;
return NULL;
}
/*
* AddBufferToRing -- add a buffer to the buffer ring
*
@ -695,25 +724,31 @@ static void AddBufferToRing(BufferAccessStrategy strategy, volatile BufferDesc *
* Returns true if buffer manager should ask for a new victim, and false
* if this buffer should be written and re-used.
*/
/*
true
false
*/
bool StrategyRejectBuffer(BufferAccessStrategy strategy, BufferDesc *buf)
{
/* We only do this in bulkread mode */
/* 只在批量读取模式下执行此操作 */
if (strategy->btype != BAS_BULKREAD)
return false;
return false; // 如果不是批量读取模式,则不进行拒绝操作
/* Don't muck with behavior of normal buffer-replacement strategy */
/* 不要改变正常缓冲区替换策略的行为 */
if (!strategy->current_was_in_ring || strategy->buffers[strategy->current] != BufferDescriptorGetBuffer(buf))
return false;
return false; // 如果当前槽位不在环中,或者环中的缓冲区与给定的缓冲区描述符不匹配,则不进行拒绝操作
/*
* Remove the dirty buffer from the ring; necessary to prevent infinite
* loop if all ring members are dirty.
*
*/
strategy->buffers[strategy->current] = InvalidBuffer;
return true;
return true; // 返回true表示已经拒绝了缓冲区
}
void StrategyGetRingPrefetchQuantityAndTrigger(BufferAccessStrategy strategy, int *quantity, int *trigger)
{
int threshold;