postgres.git / summary / log / commit / refs

commit    df238aed1090249a2bcd21e1688a398c6f513dfd
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Sun Oct 31 19:31:29 2021 +0000
First released in: 15.0, 13.5, 14.1

    Avoid O(N^2) behavior when the standby process releases many locks.
    
    When replaying a transaction that held many exclusive locks on the
    primary, a standby server's startup process would expend O(N^2)
    effort on manipulating the list of locks.  This code was fine when
    written, but commit 1cff1b95a made repetitive list_delete_first()
    calls inefficient, as explained in its commit message.  Fix by just
    iterating the list normally, and releasing storage only when done.
    (This'd be inadequate if we needed to recover from an error occurring
    partway through; but we don't.)
    
    Back-patch to v13 where 1cff1b95a came in.
    
    Nathan Bossart
    
    Discussion: https://postgr.es/m/CD2F0E7F-9822-45EC-A411-AE56F14DEA9F@amazon.com


src/backend/storage/ipc/standby.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c index 448e2b646d7..fdc4d4e61a7 100644 --- a/src/backend/storage/ipc/standby.c +++ b/src/backend/storage/ipc/standby.c @@ -791,9 +791,11 @@ StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid) static void StandbyReleaseLockList(List *locks) { - while (locks) + ListCell *lc; + + foreach(lc, locks) { - xl_standby_lock *lock = (xl_standby_lock *) linitial(locks); + xl_standby_lock *lock = (xl_standby_lock *) lfirst(lc); LOCKTAG locktag; elog(trace_recovery(DEBUG4), @@ -807,9 +809,9 @@ StandbyReleaseLockList(List *locks) lock->xid, lock->dbOid, lock->relOid); Assert(false); } - pfree(lock); - locks = list_delete_first(locks); } + + list_free_deep(locks); } static void [parent: 4cd72add0579]