Re: refactoring relation extension and BufferAlloc(), faster COPY
Andres Freund <andres@anarazel.de>
Hi, On 2022-10-29 18:33:53 +0530, Bharath Rupireddy wrote: > On Sat, Oct 29, 2022 at 8:24 AM Andres Freund <andres@anarazel.de> wrote: > > > > Hi, > > > > I'm working to extract independently useful bits from my AIO work, to reduce > > the size of that patchset. This is one of those pieces. > > Thanks a lot for this great work. There are 12 patches in this thread, > I believe each of these patches is trying to solve separate problems > and can be reviewed and get committed separately, am I correct? Mostly, yes. For 0001 I already started https://www.postgresql.org/message-id/20221027165914.2hofzp4cvutj6gin%40awork3.anarazel.de to discuss the specific issue. We don't strictly need v1-0002-aio-Add-some-error-checking-around-pinning.patch but I did find it useful. v1-0012-bufmgr-debug-Add-PrintBuffer-Desc.patch is not used in the patch series, but I found it quite useful when debugging issues with the patch. A heck of a lot easier to interpret page flags when they can be printed. I also think there's some architectural questions that'll influence the number of patches. E.g. I'm not convinced v1-0010-heapam-Add-num_pages-to-RelationGetBufferForTuple.patch is quite the right spot to track which additional pages should be used. It could very well instead be alongside ->smgr_targblock. Possibly the best path would instead be to return the additional pages explicitly to callers of RelationGetBufferForTuple, but RelationGetBufferForTuple does a bunch of work around pinning that potentially would need to be repeated in heap_multi_insert(). > > In workloads that extend relations a lot, we end up being extremely contended > > on the relation extension lock. We've attempted to address that to some degree > > by using batching, which helps, but only so much. > > Yes, I too have observed this in the past for parallel inserts in CTAS > work - https://www.postgresql.org/message-id/CALj2ACW9BUoFqWkmTSeHjFD-W7_00s3orqSvtvUk%2BKD2H7ZmRg%40mail.gmail.com. > Tackling bulk relation extension problems will unblock the parallel > inserts (in CTAS, COPY) work I believe. Yea. There's a lot of places the current approach ended up being a bottleneck. > Firstly, 0001 avoids extra loop over waiters and looks a reasonable > change, some comments on the patch: > 1) > + int lwWaiting; /* 0 if not waiting, 1 if on > waitlist, 2 if > + * waiting to be woken */ > Use macros instead of hard-coded values for better readability? > > #define PROC_LW_LOCK_NOT_WAITING 0 > #define PROC_LW_LOCK_ON_WAITLIST 1 > #define PROC_LW_LOCK_WAITING_TO_BE_WOKEN 2 Yea - this was really more of a prototype patch - I noted that we'd want to use defines for this in https://www.postgresql.org/message-id/20221027165914.2hofzp4cvutj6gin%40awork3.anarazel.de > 3) > + proclist_delete(&lock->waiters, MyProc->pgprocno, lwWaitLink); > + found = true; > I guess 'found' is a bit meaningless here as we are doing away with > the proclist_foreach_modify loop. We can directly use > MyProc->lwWaiting == 1 and remove 'found'. We can rename it, but I think we still do need it, it's easier to analyze the logic if the relevant check happens on a value from while we held the wait list lock. Probably should do the reset inside the locked section as well. > 4) > if (!MyProc->lwWaiting) > if (!proc->lwWaiting) > Can we modify the above conditions in lwlock.c to MyProc->lwWaiting != > 1 or PROC_LW_LOCK_ON_WAITLIST or the macro? I think it's better to check it's 0, rather than just != 1. > 5) Is there any specific test case that I can see benefit of this > patch? If yes, can you please share it here? Yep, see the other thread, there's a pretty easy case there. You can also see it at extreme client counts with a pgbench -S against a cluster with a smaller shared_buffers. But the difference is not huge before something like 2048-4096 clients, and then it only occurs occasionally (because you need to end up with most connections waiting for one of the partitions). So the test case from the other thread is a lot better. Greetings, Andres Freund
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