Re: SAVEPOINTs and COMMIT performance

Lists: pgsql-hackers
From: Simon Riggs <simon(at)2ndQuadrant(dot)com>
To: pgsql-hackers(at)postgresql(dot)org
Subject: SAVEPOINTs and COMMIT performance
Date: 2010-07-20 18:11:47
Message-ID: 1279649507.1739.3367.camel@ebony
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers


As part of a performance investigation for a customer I've noticed an
O(N^2) performance issue on COMMITs of transactions that contain many
SAVEPOINTs. I've consistently measured COMMIT times of around 9 seconds,
with 49% CPU, mostly in LockReassignCurrentOwner().

BEGIN;
INSERT...
SAVEPOINT ...
INSERT...
SAVEPOINT ...
... (repeat 10,000 times)
COMMIT;

The way SAVEPOINTs work is that each is nested within the previous one,
so that at COMMIT time we must recursively commit all the
subtransactions before we issue final commit.

That's a shame because ResourceOwnerReleaseInternal() contains an
optimisation to speed up final commit, by calling ProcReleaseLocks().

What we actually do is recursively call LockReassignCurrentOwner() which
sequentially scans LockMethodLocalHash at each level of transaction. The
comments refer to this as "retail" rather than the wholesale method,
which never gets to execute anything worthwhile in this case.

This issue does NOT occur in PLpgSQL functions that contain many
EXCEPTION clauses in a loop, since in that case the subtransactions are
started and committed from the top level so that the subxact nesting
never goes too deep.

Fix looks like we need special handling for the depth-first case, rather
than just a recursion loop in CommitTransactionCommand().

Issues looks like it goes all the way back, no fix for 9.0.

I notice also that the nesting model of SAVEPOINTs also means that
read-only subtransactions will still generate an xid when followed by a
DML statement. That's unnecessary, but required given current design.

--
Simon Riggs www.2ndQuadrant.com
PostgreSQL Development, 24x7 Support, Training and Services


From: Bruce Momjian <bruce(at)momjian(dot)us>
To: Simon Riggs <simon(at)2ndQuadrant(dot)com>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: SAVEPOINTs and COMMIT performance
Date: 2011-02-06 17:11:04
Message-ID: 201102061711.p16HB4Z01831@momjian.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers


Did this ever get addressed?

---------------------------------------------------------------------------

Simon Riggs wrote:
>
> As part of a performance investigation for a customer I've noticed an
> O(N^2) performance issue on COMMITs of transactions that contain many
> SAVEPOINTs. I've consistently measured COMMIT times of around 9 seconds,
> with 49% CPU, mostly in LockReassignCurrentOwner().
>
> BEGIN;
> INSERT...
> SAVEPOINT ...
> INSERT...
> SAVEPOINT ...
> ... (repeat 10,000 times)
> COMMIT;
>
> The way SAVEPOINTs work is that each is nested within the previous one,
> so that at COMMIT time we must recursively commit all the
> subtransactions before we issue final commit.
>
> That's a shame because ResourceOwnerReleaseInternal() contains an
> optimisation to speed up final commit, by calling ProcReleaseLocks().
>
> What we actually do is recursively call LockReassignCurrentOwner() which
> sequentially scans LockMethodLocalHash at each level of transaction. The
> comments refer to this as "retail" rather than the wholesale method,
> which never gets to execute anything worthwhile in this case.
>
> This issue does NOT occur in PLpgSQL functions that contain many
> EXCEPTION clauses in a loop, since in that case the subtransactions are
> started and committed from the top level so that the subxact nesting
> never goes too deep.
>
> Fix looks like we need special handling for the depth-first case, rather
> than just a recursion loop in CommitTransactionCommand().
>
> Issues looks like it goes all the way back, no fix for 9.0.
>
> I notice also that the nesting model of SAVEPOINTs also means that
> read-only subtransactions will still generate an xid when followed by a
> DML statement. That's unnecessary, but required given current design.
>
> --
> Simon Riggs www.2ndQuadrant.com
> PostgreSQL Development, 24x7 Support, Training and Services
>
>
> --
> Sent via pgsql-hackers mailing list (pgsql-hackers(at)postgresql(dot)org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-hackers

--
Bruce Momjian <bruce(at)momjian(dot)us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +


From: Simon Riggs <simon(at)2ndQuadrant(dot)com>
To: Bruce Momjian <bruce(at)momjian(dot)us>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: SAVEPOINTs and COMMIT performance
Date: 2011-02-06 21:09:30
Message-ID: 1297026570.1770.2730.camel@ebony
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On Sun, 2011-02-06 at 12:11 -0500, Bruce Momjian wrote:
> Did this ever get addressed?

Patch attached.

Seems like the easiest fix I can come up with.

> Simon Riggs wrote:
> >
> > As part of a performance investigation for a customer I've noticed an
> > O(N^2) performance issue on COMMITs of transactions that contain many
> > SAVEPOINTs. I've consistently measured COMMIT times of around 9 seconds,
> > with 49% CPU, mostly in LockReassignCurrentOwner().
> >
> > BEGIN;
> > INSERT...
> > SAVEPOINT ...
> > INSERT...
> > SAVEPOINT ...
> > ... (repeat 10,000 times)
> > COMMIT;
> >
> > The way SAVEPOINTs work is that each is nested within the previous one,
> > so that at COMMIT time we must recursively commit all the
> > subtransactions before we issue final commit.
> >
> > That's a shame because ResourceOwnerReleaseInternal() contains an
> > optimisation to speed up final commit, by calling ProcReleaseLocks().
> >
> > What we actually do is recursively call LockReassignCurrentOwner() which
> > sequentially scans LockMethodLocalHash at each level of transaction. The
> > comments refer to this as "retail" rather than the wholesale method,
> > which never gets to execute anything worthwhile in this case.
> >
> > This issue does NOT occur in PLpgSQL functions that contain many
> > EXCEPTION clauses in a loop, since in that case the subtransactions are
> > started and committed from the top level so that the subxact nesting
> > never goes too deep.
> >
> > Fix looks like we need special handling for the depth-first case, rather
> > than just a recursion loop in CommitTransactionCommand().
> >
> > Issues looks like it goes all the way back, no fix for 9.0.
> >
> > I notice also that the nesting model of SAVEPOINTs also means that
> > read-only subtransactions will still generate an xid when followed by a
> > DML statement. That's unnecessary, but required given current design.
> >
> > --
> > Simon Riggs www.2ndQuadrant.com
> > PostgreSQL Development, 24x7 Support, Training and Services
> >
> >
> > --
> > Sent via pgsql-hackers mailing list (pgsql-hackers(at)postgresql(dot)org)
> > To make changes to your subscription:
> > http://www.postgresql.org/mailpref/pgsql-hackers
>

--
Simon Riggs http://www.2ndQuadrant.com/books/
PostgreSQL Development, 24x7 Support, Training and Services

Attachment Content-Type Size
savepoint_commit_performance.v1.patch text/x-patch 2.6 KB

From: Bruce Momjian <bruce(at)momjian(dot)us>
To: Simon Riggs <simon(at)2ndQuadrant(dot)com>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: SAVEPOINTs and COMMIT performance
Date: 2011-03-11 12:18:27
Message-ID: 201103111218.p2BCIRP15781@momjian.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers


What happened to this patch?

---------------------------------------------------------------------------

Simon Riggs wrote:
> On Sun, 2011-02-06 at 12:11 -0500, Bruce Momjian wrote:
> > Did this ever get addressed?
>
> Patch attached.
>
> Seems like the easiest fix I can come up with.
>
> > Simon Riggs wrote:
> > >
> > > As part of a performance investigation for a customer I've noticed an
> > > O(N^2) performance issue on COMMITs of transactions that contain many
> > > SAVEPOINTs. I've consistently measured COMMIT times of around 9 seconds,
> > > with 49% CPU, mostly in LockReassignCurrentOwner().
> > >
> > > BEGIN;
> > > INSERT...
> > > SAVEPOINT ...
> > > INSERT...
> > > SAVEPOINT ...
> > > ... (repeat 10,000 times)
> > > COMMIT;
> > >
> > > The way SAVEPOINTs work is that each is nested within the previous one,
> > > so that at COMMIT time we must recursively commit all the
> > > subtransactions before we issue final commit.
> > >
> > > That's a shame because ResourceOwnerReleaseInternal() contains an
> > > optimisation to speed up final commit, by calling ProcReleaseLocks().
> > >
> > > What we actually do is recursively call LockReassignCurrentOwner() which
> > > sequentially scans LockMethodLocalHash at each level of transaction. The
> > > comments refer to this as "retail" rather than the wholesale method,
> > > which never gets to execute anything worthwhile in this case.
> > >
> > > This issue does NOT occur in PLpgSQL functions that contain many
> > > EXCEPTION clauses in a loop, since in that case the subtransactions are
> > > started and committed from the top level so that the subxact nesting
> > > never goes too deep.
> > >
> > > Fix looks like we need special handling for the depth-first case, rather
> > > than just a recursion loop in CommitTransactionCommand().
> > >
> > > Issues looks like it goes all the way back, no fix for 9.0.
> > >
> > > I notice also that the nesting model of SAVEPOINTs also means that
> > > read-only subtransactions will still generate an xid when followed by a
> > > DML statement. That's unnecessary, but required given current design.
> > >
> > > --
> > > Simon Riggs www.2ndQuadrant.com
> > > PostgreSQL Development, 24x7 Support, Training and Services
> > >
> > >
> > > --
> > > Sent via pgsql-hackers mailing list (pgsql-hackers(at)postgresql(dot)org)
> > > To make changes to your subscription:
> > > http://www.postgresql.org/mailpref/pgsql-hackers
> >
>
> --
> Simon Riggs http://www.2ndQuadrant.com/books/
> PostgreSQL Development, 24x7 Support, Training and Services
>

[ Attachment, skipping... ]

--
Bruce Momjian <bruce(at)momjian(dot)us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ It's impossible for everything to be true. +


From: Robert Haas <robertmhaas(at)gmail(dot)com>
To: Bruce Momjian <bruce(at)momjian(dot)us>
Cc: Simon Riggs <simon(at)2ndquadrant(dot)com>, pgsql-hackers(at)postgresql(dot)org
Subject: Re: SAVEPOINTs and COMMIT performance
Date: 2011-03-11 12:53:34
Message-ID: AANLkTimnNcgXqny9nd0Pddyx8+TAHdo01B2jJWC8z7-g@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Mar 11, 2011 at 7:18 AM, Bruce Momjian <bruce(at)momjian(dot)us> wrote:
> What happened to this patch?

I added it to the next CommitFest. It would be reasonably to apply it
sooner, perhaps, but nobody's reviewed it. Want to volunteer?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


From: Heikki Linnakangas <heikki(dot)linnakangas(at)enterprisedb(dot)com>
To: Simon Riggs <simon(at)2ndQuadrant(dot)com>
Cc: Bruce Momjian <bruce(at)momjian(dot)us>, pgsql-hackers(at)postgresql(dot)org
Subject: Re: SAVEPOINTs and COMMIT performance
Date: 2011-06-06 09:33:21
Message-ID: 4DEC9EE1.8040802@enterprisedb.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On 06.02.2011 23:09, Simon Riggs wrote:
> On Sun, 2011-02-06 at 12:11 -0500, Bruce Momjian wrote:
>> Did this ever get addressed?
>
> Patch attached.
>
> Seems like the easiest fix I can come up with.

> @@ -2518,7 +2518,7 @@ CommitTransactionCommand(void)
> case TBLOCK_SUBEND:
> do
> {
> - CommitSubTransaction();
> + CommitSubTransaction(true);
> s = CurrentTransactionState; /* changed by pop */
> } while (s->blockState == TBLOCK_SUBEND);
> /* If we had a COMMIT command, finish off the main xact too */

We also get into this codepath at RELEASE SAVEPOINT, in which case it is
wrong to not reassign the locks to the parent subtransaction.

--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com


From: Simon Riggs <simon(at)2ndQuadrant(dot)com>
To: Heikki Linnakangas <heikki(dot)linnakangas(at)enterprisedb(dot)com>
Cc: Bruce Momjian <bruce(at)momjian(dot)us>, pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: SAVEPOINTs and COMMIT performance
Date: 2011-06-06 19:18:28
Message-ID: BANLkTimbG+BeW7x0Z-RowvMcuE7=p8rk1w@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Jun 6, 2011 at 10:33 AM, Heikki Linnakangas
<heikki(dot)linnakangas(at)enterprisedb(dot)com> wrote:
> On 06.02.2011 23:09, Simon Riggs wrote:
>>
>> On Sun, 2011-02-06 at 12:11 -0500, Bruce Momjian wrote:
>>>
>>> Did this ever get addressed?
>>
>> Patch attached.
>>
>> Seems like the easiest fix I can come up with.
>
>> @@ -2518,7 +2518,7 @@ CommitTransactionCommand(void)
>>                case TBLOCK_SUBEND:
>>                        do
>>                        {
>> -                               CommitSubTransaction();
>> +                               CommitSubTransaction(true);
>>                                s = CurrentTransactionState;    /* changed
>> by pop */
>>                        } while (s->blockState == TBLOCK_SUBEND);
>>                        /* If we had a COMMIT command, finish off the main
>> xact too */
>
> We also get into this codepath at RELEASE SAVEPOINT, in which case it is
> wrong to not reassign the locks to the parent subtransaction.

Agreed.

Thanks for the review.

I'll change that.

--
 Simon Riggs                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services


From: Simon Riggs <simon(at)2ndQuadrant(dot)com>
To: Heikki Linnakangas <heikki(dot)linnakangas(at)enterprisedb(dot)com>
Cc: pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: SAVEPOINTs and COMMIT performance
Date: 2011-07-14 14:59:14
Message-ID: CA+U5nMJnrMWAzymxLoWkoH-oxpq7L4bsUO760buupHArLp7Tgw@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Jun 6, 2011 at 10:33 AM, Heikki Linnakangas
<heikki(dot)linnakangas(at)enterprisedb(dot)com> wrote:
> On 06.02.2011 23:09, Simon Riggs wrote:
>>
>> On Sun, 2011-02-06 at 12:11 -0500, Bruce Momjian wrote:
>>>
>>> Did this ever get addressed?
>>
>> Patch attached.
>>
>> Seems like the easiest fix I can come up with.
>
>> @@ -2518,7 +2518,7 @@ CommitTransactionCommand(void)
>>                case TBLOCK_SUBEND:
>>                        do
>>                        {
>> -                               CommitSubTransaction();
>> +                               CommitSubTransaction(true);
>>                                s = CurrentTransactionState;    /* changed
>> by pop */
>>                        } while (s->blockState == TBLOCK_SUBEND);
>>                        /* If we had a COMMIT command, finish off the main
>> xact too */
>
> We also get into this codepath at RELEASE SAVEPOINT, in which case it is
> wrong to not reassign the locks to the parent subtransaction.

Attached patch splits TBLOCK_SUBEND state into two new states:
TBLOCK_SUBCOMMIT and TBLOCK_SUBRELEASE, so that we can do the right
thing.

--
 Simon Riggs                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services

Attachment Content-Type Size
savepoint_commit_performance.v2.patch application/octet-stream 8.7 KB