Re: refactoring relation extension and BufferAlloc(), faster COPY
Heikki Linnakangas <hlinnaka@iki.fi>
On 21/02/2023 18:33, Alvaro Herrera wrote:
> On 2023-Feb-21, Heikki Linnakangas wrote:
>
>>> +static BlockNumber
>>> +BulkExtendSharedRelationBuffered(Relation rel,
>>> + SMgrRelation smgr,
>>> + bool skip_extension_lock,
>>> + char relpersistence,
>>> + ForkNumber fork, ReadBufferMode mode,
>>> + BufferAccessStrategy strategy,
>>> + uint32 *num_pages,
>>> + uint32 num_locked_pages,
>>> + Buffer *buffers)
>>
>> Ugh, that's a lot of arguments, some are inputs and some are outputs. I
>> don't have any concrete suggestions, but could we simplify this somehow?
>> Needs a comment at least.
>
> Yeah, I noticed this too. I think it would be easy enough to add a new
> struct that can be passed as a pointer, which can be stack-allocated
> by the caller, and which holds the input arguments that are common to
> both functions, as is sensible.
We also do this in freespace.c and visibilitymap.c:
/* Extend as needed. */
while (fsm_nblocks_now < fsm_nblocks)
{
PageSetChecksumInplace((Page) pg.data, fsm_nblocks_now);
smgrextend(reln, FSM_FORKNUM, fsm_nblocks_now,
pg.data, false);
fsm_nblocks_now++;
}
We could use the new smgrzeroextend function here. But it would be
better to go through the buffer cache, because after this, the last
block, at 'fsm_nblocks', will be read with ReadBuffer() and modified.
We could use BulkExtendSharedRelationBuffered() to extend the relation
and keep the last page locked, but the
BulkExtendSharedRelationBuffered() signature doesn't allow that. It can
return the first N pages locked, but there's no way to return the *last*
page locked.
Perhaps we should decompose this function into several function calls.
Something like:
/* get N victim buffers, pinned and !BM_VALID */
buffers = BeginExtendRelation(int npages);
LockRelationForExtension(rel)
/* Insert buffers into buffer table */
first_blk = smgrnblocks()
for (blk = first_blk; blk < last_blk; blk++)
MapNewBuffer(blk, buffers[i])
/* extend the file on disk */
smgrzeroextend();
UnlockRelationForExtension(rel)
for (blk = first_blk; blk < last_blk; blk++)
{
memset(BufferGetPage(buffers[i]), 0,
FinishNewBuffer(buffers[i])
/* optionally lock the buffer */
LockBuffer(buffers[i]);
}
That's a lot more verbose, of course, but gives the callers the
flexibility. And might even be more readable than one function call with
lots of arguments.
This would expose the concept of a buffer that's mapped but marked as
IO-in-progress outside bufmgr.c. On one hand, maybe that's exposing
details that shouldn't be exposed. On the other hand, it might come
handy. Instead of RBM_ZERO_AND_LOCK mode, for example, it might be handy
to have a function that returns an IO-in-progress buffer that you can
initialize any way you want.
- Heikki
Commits
-
lwlock: Fix quadratic behavior with very long wait lists
- 81038228582a 12.18 landed
- dc9d424cf0cd 13.14 landed
- 5f6ec27a6477 14.11 landed
- f374fb4aab3e 15.6 landed
- a4adc31f6902 16.0 landed
-
Support RBM_ZERO_AND_CLEANUP_LOCK in ExtendBufferedRelTo(), add tests
- 43a33ef54e50 16.0 landed
-
Use ExtendBufferedRelTo() in XLogReadBufferExtended()
- 26158b852d3a 16.0 landed
-
hio: Use ExtendBufferedRelBy() to extend tables more efficiently
- 00d1e02be249 16.0 landed
-
heapam: Pass number of required pages to RelationGetBufferForTuple()
- 5279e9db8e8d 16.0 landed
-
Convert many uses of ReadBuffer[Extended](P_NEW) to ExtendBufferedRel()
- acab1b0914e4 16.0 landed
-
Use ExtendBufferedRelTo() in {vm,fsm}_extend()
- fcdda1e4b502 16.0 landed
-
bufmgr: Introduce infrastructure for faster relation extension
- 31966b151e6a 16.0 landed
-
bufmgr: Support multiple in-progress IOs by using resowner
- 12f3867f5534 16.0 landed
-
bufmgr: Acquire and clean victim buffer separately
- dad50f677c42 16.0 landed
-
bufmgr: Add Pin/UnpinLocalBuffer()
- 794f25944790 16.0 landed
-
bufmgr: Add some more error checking [infrastructure] around pinning
- 819b69a81d30 16.0 landed
-
Add smgrzeroextend(), FileZero(), FileFallocate()
- 4d330a61bb19 16.0 landed
-
Don't initialize page in {vm,fsm}_extend(), not needed
- 3d6a98457d8e 16.0 landed
-
bufmgr: Remove buffer-write-dirty tracepoints
- 8a2b1b147728 16.0 landed
-
hio: Release extension lock before initializing page / pinning VM
- 14f98e0af996 16.0 landed
-
bufmgr: Fix undefined behaviour with, unrealistically, large temp_buffers
- 558cf8038768 16.0 landed
-
Fix memory leak and inefficiency in CREATE DATABASE ... STRATEGY WAL_LOG
- 5df319f3d55d 16.0 cited
-
pgstat: Track more detailed relation IO statistics
- f30d62c2fc60 16.0 cited
-
Use unnamed POSIX semaphores on Cygwin.
- f2857af485a0 16.0 cited
-
Include RelFileLocator fields individually in BufferTag.
- 82ac34db2036 16.0 cited