On Tue, Nov 15, 2011 at 1:50 PM, Robert Haas <robertmhaas@gmail.com> wrote:
> It basically
> works like a regular LWLock, except that it has a special operation to
> optimize ProcArrayEndTransaction(). In the uncontended case, instead
> of acquiring and releasing the lock, it just grabs the lock, observes
> that there is no contention, clears the critical PGPROC fields (which
> isn't noticeably slower than updating the state of the lock would be)
> and releases the spin lock. There's then no need to reacquire the
> spinlock to "release" the lock; we're done. In the contended case,
> the backend wishing to end adds itself to a queue of ending
> transactions. When ProcArrayLock is released, the last person out
> clears the PGPROC structures for all the waiters and wakes them all
> up; they don't need to reacquire the lock, because the work they
> wished to perform while holding it is already done. Thus, in the
> *worst* case, ending transactions only need to acquire the spinlock
> protecting ProcArrayLock half as often (once instead of twice), and in
> the best case (where backends have to keep retrying only to repeatedly
> fail to get the lock) it's far better than that.
Which is the same locking avoidance technique we already use for sync
rep and for the new group commit patch.
I've been saying for some time that we should use the same technique
for ProcArray and clog also, so we only need to queue once rather than
queue three times at end of each transaction.
I'm not really enthused by the idea of completely rewriting lwlocks
for this. Seems like specialised code is likely to be best, as well as
having less collateral damage.
With that in mind, should we try to fuse the group commit with the
procarraylock approach, so we just queue once and get woken when all
the activities have been handled? If the first woken proc performs the
actions then wakes people further down the queue it could work quite
well.
--
Simon Riggs http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services