diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 3924a51..f4267ed 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -75,6 +75,12 @@ double bgwriter_lru_multiplier = 2.0; */ int target_prefetch_pages = 0; +/* + * Counters to measure bgwriter effectiveness. + */ +uint64 bgwriter_clean_dirty_before_evict = 0; +uint64 bgwriter_clean_evict_before_dirty = 0; + /* local state for StartBufferIO and related functions */ static volatile BufferDesc *InProgressBuf = NULL; static bool IsForInput; @@ -804,7 +810,9 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum, * 1 so that the buffer can survive one clock-sweep pass.) */ buf->tag = newTag; - buf->flags &= ~(BM_VALID | BM_DIRTY | BM_JUST_DIRTIED | BM_CHECKPOINT_NEEDED | BM_IO_ERROR | BM_PERMANENT); + if ((buf->flags & BM_BGWRITER_CLEANED) != 0) + ++bgwriter_clean_evict_before_dirty; + buf->flags &= ~(BM_VALID | BM_DIRTY | BM_JUST_DIRTIED | BM_CHECKPOINT_NEEDED | BM_IO_ERROR | BM_PERMANENT | BM_BGWRITER_CLEANED); if (relpersistence == RELPERSISTENCE_PERMANENT) buf->flags |= BM_TAG_VALID | BM_PERMANENT; else @@ -976,6 +984,11 @@ MarkBufferDirty(Buffer buffer) if (!(bufHdr->flags & BM_DIRTY)) dirtied = true; + if ((bufHdr->flags & BM_BGWRITER_CLEANED) != 0) + { + ++bgwriter_clean_dirty_before_evict; + bufHdr->flags &= ~BM_BGWRITER_CLEANED; + } bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED); @@ -1650,6 +1663,13 @@ SyncOneBuffer(int buf_id, bool skip_recently_used) } /* + * If skip_recently_used = true, then this is the bgwriter doing cleaning. + * If it's false, this is a checkpoint, so we don't set the flag. + */ + if (skip_recently_used) + bufHdr->flags |= BM_BGWRITER_CLEANED; + + /* * Pin it, share-lock it, write it. (FlushBuffer will do nothing if the * buffer is clean by the time we've locked it.) */ @@ -1729,6 +1749,11 @@ AtProcExit_Buffers(int code, Datum arg) /* localbuf.c needs a chance too */ AtProcExit_LocalBuffers(); + + elog(LOG, + "bgwriter_clean: " UINT64_FORMAT " evict-before-dirty, " + UINT64_FORMAT " dirty-before-evict", + bgwriter_clean_evict_before_dirty, bgwriter_clean_dirty_before_evict); } /* @@ -2360,7 +2385,14 @@ SetBufferCommitInfoNeedsSave(Buffer buffer) LockBufHdr(bufHdr); Assert(bufHdr->refcount > 0); if (!(bufHdr->flags & BM_DIRTY)) + { dirtied = true; + if ((bufHdr->flags & BM_BGWRITER_CLEANED) != 0) + { + ++bgwriter_clean_dirty_before_evict; + bufHdr->flags &= ~BM_BGWRITER_CLEANED; + } + } bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED); UnlockBufHdr(bufHdr); diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h index e43719e..dc70530 100644 --- a/src/include/storage/buf_internals.h +++ b/src/include/storage/buf_internals.h @@ -39,6 +39,7 @@ #define BM_CHECKPOINT_NEEDED (1 << 7) /* must write for checkpoint */ #define BM_PERMANENT (1 << 8) /* permanent relation (not * unlogged) */ +#define BM_BGWRITER_CLEANED (1 << 9) /* bg writer has cleaned it */ typedef bits16 BufFlags;