From b4e0741727685443657b55932da0c06f028fbc00 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Wed, 1 Feb 2012 20:35:42 -0500 Subject: [PATCH] Avoid re-checking for visibility map extension too frequently. When testing bits (but not when setting or clearing them), we now won't check whether the map has been extended. This significantly improves performance in the case where the visibility map doesn't exist yet, by avoiding an extra system call per tuple. To make sure backends notice eventually, send an smgr inval on VM extension. Dean Rasheed, with minor modifications by me. --- src/backend/access/heap/visibilitymap.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/backend/access/heap/visibilitymap.c b/src/backend/access/heap/visibilitymap.c index 76b3a46780..6505e76dae 100644 --- a/src/backend/access/heap/visibilitymap.c +++ b/src/backend/access/heap/visibilitymap.c @@ -88,6 +88,7 @@ #include "storage/bufmgr.h" #include "storage/lmgr.h" #include "storage/smgr.h" +#include "utils/inval.h" /*#define TRACE_VISIBILITYMAP */ @@ -482,16 +483,20 @@ vm_readbuf(Relation rel, BlockNumber blkno, bool extend) { Buffer buf; + /* + * We might not have opened the relation at the smgr level yet, or we might + * have been forced to close it by a sinval message. The code below won't + * necessarily notice relation extension immediately when extend = false, + * so we rely on sinval messages to ensure that our ideas about the size of + * the map aren't too far out of date. + */ RelationOpenSmgr(rel); /* * If we haven't cached the size of the visibility map fork yet, check it - * first. Also recheck if the requested block seems to be past end, since - * our cached value might be stale. (We send smgr inval messages on - * truncation, but not on extension.) + * first. */ - if (rel->rd_smgr->smgr_vm_nblocks == InvalidBlockNumber || - blkno >= rel->rd_smgr->smgr_vm_nblocks) + if (rel->rd_smgr->smgr_vm_nblocks == InvalidBlockNumber) { if (smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM)) rel->rd_smgr->smgr_vm_nblocks = smgrnblocks(rel->rd_smgr, @@ -560,6 +565,7 @@ vm_extend(Relation rel, BlockNumber vm_nblocks) vm_nblocks_now = smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM); + /* Now extend the file */ while (vm_nblocks_now < vm_nblocks) { smgrextend(rel->rd_smgr, VISIBILITYMAP_FORKNUM, vm_nblocks_now, @@ -567,6 +573,15 @@ vm_extend(Relation rel, BlockNumber vm_nblocks) vm_nblocks_now++; } + /* + * Send a shared-inval message to force other backends to close any smgr + * references they may have for this rel, which we are about to change. + * This is a useful optimization because it means that backends don't have + * to keep checking for creation or extension of the file, which happens + * infrequently. + */ + CacheInvalidateSmgr(rel->rd_smgr->smgr_rnode); + /* Update local cache with the up-to-date size */ rel->rd_smgr->smgr_vm_nblocks = vm_nblocks_now; -- 2.40.0