diff options
Diffstat (limited to 'src/backend/storage')
-rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 59 | ||||
-rw-r--r-- | src/backend/storage/buffer/localbuf.c | 39 | ||||
-rw-r--r-- | src/backend/storage/file/fd.c | 38 | ||||
-rw-r--r-- | src/backend/storage/smgr/md.c | 22 | ||||
-rw-r--r-- | src/backend/storage/smgr/smgr.c | 15 |
5 files changed, 167 insertions, 6 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 6046f6ef6aa..534c7516f78 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.244 2009/01/01 17:23:47 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.245 2009/01/12 05:10:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -65,6 +65,13 @@ bool zero_damaged_pages = false; int bgwriter_lru_maxpages = 100; double bgwriter_lru_multiplier = 2.0; +/* + * How many buffers PrefetchBuffer callers should try to stay ahead of their + * ReadBuffer calls by. This is maintained by the assign hook for + * effective_io_concurrency. Zero means "never prefetch". + */ +int target_prefetch_pages = 0; + /* local state for StartBufferIO and related functions */ static volatile BufferDesc *InProgressBuf = NULL; static bool IsForInput; @@ -96,6 +103,56 @@ static void AtProcExit_Buffers(int code, Datum arg); /* + * PrefetchBuffer -- initiate asynchronous read of a block of a relation + * + * This is named by analogy to ReadBuffer but doesn't actually allocate a + * buffer. Instead it tries to ensure that a future ReadBuffer for the given + * block will not be delayed by the I/O. Prefetching is optional. + * No-op if prefetching isn't compiled in. + */ +void +PrefetchBuffer(Relation reln, ForkNumber forkNum, BlockNumber blockNum) +{ +#ifdef USE_PREFETCH + Assert(RelationIsValid(reln)); + Assert(BlockNumberIsValid(blockNum)); + + /* Open it at the smgr level if not already done */ + RelationOpenSmgr(reln); + + if (reln->rd_istemp) + { + /* pass it off to localbuf.c */ + LocalPrefetchBuffer(reln->rd_smgr, forkNum, blockNum); + } + else + { + BufferTag newTag; /* identity of requested block */ + uint32 newHash; /* hash value for newTag */ + LWLockId newPartitionLock; /* buffer partition lock for it */ + int buf_id; + + /* create a tag so we can lookup the buffer */ + INIT_BUFFERTAG(newTag, reln->rd_smgr->smgr_rnode, forkNum, blockNum); + + /* determine its hash code and partition lock ID */ + newHash = BufTableHashCode(&newTag); + newPartitionLock = BufMappingPartitionLock(newHash); + + /* see if the block is in the buffer pool already */ + LWLockAcquire(newPartitionLock, LW_SHARED); + buf_id = BufTableLookup(&newTag, newHash); + LWLockRelease(newPartitionLock); + + /* If not in buffers, initiate prefetch */ + if (buf_id < 0) + smgrprefetch(reln->rd_smgr, forkNum, blockNum); + } +#endif /* USE_PREFETCH */ +} + + +/* * ReadBuffer -- a shorthand for ReadBufferExtended, for reading from main * fork with RBM_NORMAL mode and default strategy. */ diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c index 4dd5619f39f..5431419cfe6 100644 --- a/src/backend/storage/buffer/localbuf.c +++ b/src/backend/storage/buffer/localbuf.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.85 2009/01/01 17:23:47 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.86 2009/01/12 05:10:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,43 @@ static Block GetLocalBufferStorage(void); /* + * LocalPrefetchBuffer - + * initiate asynchronous read of a block of a relation + * + * Do PrefetchBuffer's work for temporary relations. + * No-op if prefetching isn't compiled in. + */ +void +LocalPrefetchBuffer(SMgrRelation smgr, ForkNumber forkNum, + BlockNumber blockNum) +{ +#ifdef USE_PREFETCH + BufferTag newTag; /* identity of requested block */ + LocalBufferLookupEnt *hresult; + + INIT_BUFFERTAG(newTag, smgr->smgr_rnode, forkNum, blockNum); + + /* Initialize local buffers if first request in this session */ + if (LocalBufHash == NULL) + InitLocalBuffers(); + + /* See if the desired buffer already exists */ + hresult = (LocalBufferLookupEnt *) + hash_search(LocalBufHash, (void *) &newTag, HASH_FIND, NULL); + + if (hresult) + { + /* Yes, so nothing to do */ + return; + } + + /* Not in buffers, so initiate prefetch */ + smgrprefetch(smgr, forkNum, blockNum); +#endif /* USE_PREFETCH */ +} + + +/* * LocalBufferAlloc - * Find or create a local buffer for the given page of the given relation. * diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index f67ab94fd52..b91946a0350 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.146 2009/01/01 17:23:47 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.147 2009/01/12 05:10:44 tgl Exp $ * * NOTES: * @@ -1029,6 +1029,42 @@ FileClose(File file) FreeVfd(file); } +/* + * FilePrefetch - initiate asynchronous read of a given range of the file. + * The logical seek position is unaffected. + * + * Currently the only implementation of this function is using posix_fadvise + * which is the simplest standardized interface that accomplishes this. + * We could add an implementation using libaio in the future; but note that + * this API is inappropriate for libaio, which wants to have a buffer provided + * to read into. + */ +int +FilePrefetch(File file, off_t offset, int amount) +{ +#if defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED) + int returnCode; + + Assert(FileIsValid(file)); + + DO_DB(elog(LOG, "FilePrefetch: %d (%s) " INT64_FORMAT " %d", + file, VfdCache[file].fileName, + (int64) offset, amount)); + + returnCode = FileAccess(file); + if (returnCode < 0) + return returnCode; + + returnCode = posix_fadvise(VfdCache[file].fd, offset, amount, + POSIX_FADV_WILLNEED); + + return returnCode; +#else + Assert(FileIsValid(file)); + return 0; +#endif +} + int FileRead(File file, char *buffer, int amount) { diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index b9c1273702f..643c75e538b 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/smgr/md.c,v 1.143 2009/01/01 17:23:48 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/smgr/md.c,v 1.144 2009/01/12 05:10:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -551,6 +551,26 @@ mdclose(SMgrRelation reln, ForkNumber forknum) } /* + * mdprefetch() -- Initiate asynchronous read of the specified block of a relation + */ +void +mdprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum) +{ +#ifdef USE_PREFETCH + off_t seekpos; + MdfdVec *v; + + v = _mdfd_getseg(reln, forknum, blocknum, false, EXTENSION_FAIL); + + seekpos = (off_t) BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE)); + Assert(seekpos < (off_t) BLCKSZ * RELSEG_SIZE); + + (void) FilePrefetch(v->mdfd_vfd, seekpos, BLCKSZ); +#endif /* USE_PREFETCH */ +} + + +/* * mdread() -- Read the specified block from a relation. */ void diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c index 6ed91bd96ff..f2cc449f175 100644 --- a/src/backend/storage/smgr/smgr.c +++ b/src/backend/storage/smgr/smgr.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.115 2009/01/01 17:23:48 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.116 2009/01/12 05:10:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -48,6 +48,8 @@ typedef struct f_smgr bool isRedo); void (*smgr_extend) (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool isTemp); + void (*smgr_prefetch) (SMgrRelation reln, ForkNumber forknum, + BlockNumber blocknum); void (*smgr_read) (SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer); void (*smgr_write) (SMgrRelation reln, ForkNumber forknum, @@ -65,7 +67,7 @@ typedef struct f_smgr static const f_smgr smgrsw[] = { /* magnetic disk */ {mdinit, NULL, mdclose, mdcreate, mdexists, mdunlink, mdextend, - mdread, mdwrite, mdnblocks, mdtruncate, mdimmedsync, + mdprefetch, mdread, mdwrite, mdnblocks, mdtruncate, mdimmedsync, mdpreckpt, mdsync, mdpostckpt } }; @@ -376,6 +378,15 @@ smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, } /* + * smgrprefetch() -- Initiate asynchronous read of the specified block of a relation. + */ +void +smgrprefetch(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum) +{ + (*(smgrsw[reln->smgr_which].smgr_prefetch)) (reln, forknum, blocknum); +} + +/* * smgrread() -- read a particular block from a relation into the supplied * buffer. * |