Re: [PATCHES] TransactionIdIsInProgress() cache

2008-03-11 Thread Alvaro Herrera
I didn't check whether your transformation is correct, but if so then it
can be changed like this and save the extra XidDidCommit call:

xvac_committed = TransactionIdDidCommit(xvac);
if (xvac_committed)
{
/* committed */
}
else if (!TransactionIdIsInProgress(xvac))
{
   if (xvac_committed)
   {
  /* committed */
   }
   else
   {
  /* aborted */
   }
}
else
{
/* in-progress */
}


-- 
Alvaro Herrerahttp://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] TransactionIdIsInProgress() cache

2008-03-11 Thread Pavan Deolasee
On Tue, Mar 11, 2008 at 6:37 PM, Alvaro Herrera
[EMAIL PROTECTED] wrote:
 I didn't check whether your transformation is correct, but if so then it
  can be changed like this and save the extra XidDidCommit call:

 xvac_committed = TransactionIdDidCommit(xvac);
 if (xvac_committed)

 {
 /* committed */
 }
 else if (!TransactionIdIsInProgress(xvac))
 {
if (xvac_committed)

{
   /* committed */
}
else
{
   /* aborted */
}
 }
 else
 {
 /* in-progress */
 }



I doubt if the transformation is correct. If xvac_committed is true, why would
one even get into the else part ?

Thanks,
Pavan

-- 
Pavan Deolasee
EnterpriseDB http://www.enterprisedb.com

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] TransactionIdIsInProgress() cache

2008-03-11 Thread Heikki Linnakangas

Alvaro Herrera wrote:

I didn't check whether your transformation is correct, but if so then it
can be changed like this and save the extra XidDidCommit call:

xvac_committed = TransactionIdDidCommit(xvac);
if (xvac_committed)
{
/* committed */
}
else if (!TransactionIdIsInProgress(xvac))
{
   if (xvac_committed)
   {
  /* committed */
   }
   else
   {
  /* aborted */
   }
}
else
{
/* in-progress */
}


Nope, that's not good. Per comments in tqual.c, you have to call 
TransactionIdIsInProgress *before* TransactionIdDidCommit, to avoid this 
race condition:


1. Xact A inserts a record
2. Xact B does TransactionIdDidCommit, which retuns false because it's 
still in progress

3. Xact B commits
4. Xact B does TransactionIdIsInProgress to see if A is still in 
progress. It returns false. We conclude that A aborted, while it 
actually committed.


My proposal was basically to add an extra TransactionIdDidCommit call 
before the TransactionIdIsInProgress call, in the hope that it returns 
true and we can skip the rest.


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

--
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] TransactionIdIsInProgress() cache

2008-03-11 Thread Alvaro Herrera
Heikki Linnakangas wrote:

 Nope, that's not good. Per comments in tqual.c, you have to call  
 TransactionIdIsInProgress *before* TransactionIdDidCommit, to avoid this  
 race condition:

 1. Xact A inserts a record
 2. Xact B does TransactionIdDidCommit, which retuns false because it's  
 still in progress
 3. Xact B commits
 4. Xact B does TransactionIdIsInProgress to see if A is still in  
 progress. It returns false. We conclude that A aborted, while it  
 actually committed.

Ah, right -- I knew there was a reason for the other coding, I just
didn't remember what it was and based my transformation purely on the
snippet you posted.

-- 
Alvaro Herrerahttp://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] TransactionIdIsInProgress() cache

2008-03-11 Thread Tom Lane
Heikki Linnakangas [EMAIL PROTECTED] writes:
 I presume the case where this would help would be when you populate a
 large table, with COPY for example, and the run a seq scan on it. As all
 rows in the table have the same xmin, you keep testing for the same XID
 over and over again.

Yeah, that's the reasoning for having the single-element cache in
transam.c in the first place.  Mass updates and mass deletes would
also result in a lot of probes of the same XID on the next examination
of the table.

Simon's idea looks sane, although TransactionIdIsKnownNotInProgress
seems a kinda weird name ... it feels like a double negative to me,
although strictly speaking it's not.  Maybe instead
TransactionIdIsKnownCompleted?

 To matter from scalability point of view, there would need to be a lot 
 of concurrent activity that compete for the lock.

I think it's probably useful just from a cycles-saved point of view.
And we do know that ProcArrayLock is a hot spot.

 Hmm. The pattern in tqual.c is:
 ...
 We could do this instead:
 ...

I dislike this alternative because tqual.c is mind-bendingly complex
already.  Simon's approach hides the issue somewhere else where there
aren't so many code paths to keep straight.

regards, tom lane

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] TransactionIdIsInProgress() cache

2008-03-11 Thread Simon Riggs
On Tue, 2008-03-11 at 12:57 +, Heikki Linnakangas wrote:

 We could do this instead:
 
   if (TransactionIdDidCommit(xvac))
   {
   /* committed */
   }
   else if (!TransactionIdIsInProgress(xvac))
   {
  if (TransactionIdDidCommit(xvac))
  {
 /* committed */
  }
  else
  {
 /* aborted */
  }
   }
   else
   {
   /* in-progress */
   }
 
 (hopefully there would be a way to macroize that or something to avoid 
 bloating the code any more.)
 
 For committed transactions, this would save the 
 TransactionIdIsInProgress call completely, whether or not it's in the 
 one-item cache. The tradeoff is that we would have to call 
 TransactionIdDidCommit twice for aborted transactions.

I thought about doing it the way you suggest but
TransactionIdIsInProgress is the offending code, so thats the part I
tuned. TransactionIdDidCommit uses the single item cache so it seemed
easier to make isolated changes as proposed rather than touching tqual
code in multiple places to do exactly the same thing.

No, I haven't done any formal performance testing on it. It seemed an
obvious hole that everyone would agree we should avoid, since we can do
it so cheaply: one integer comparison against scanning the whole
procarray and taking an LWlock.

-- 
  Simon Riggs
  2ndQuadrant  http://www.2ndQuadrant.com 

  PostgreSQL UK 2008 Conference: http://www.postgresql.org.uk


-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] TransactionIdIsInProgress() cache

2008-03-11 Thread Simon Riggs
On Tue, 2008-03-11 at 13:15 -0400, Tom Lane wrote:
 Maybe instead TransactionIdIsKnownCompleted? 

Works for me.

-- 
  Simon Riggs
  2ndQuadrant  http://www.2ndQuadrant.com 

  PostgreSQL UK 2008 Conference: http://www.postgresql.org.uk


-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] TransactionIdIsInProgress() cache

2008-03-11 Thread Tom Lane
Simon Riggs [EMAIL PROTECTED] writes:
 No, I haven't done any formal performance testing on it. It seemed an
 obvious hole that everyone would agree we should avoid, since we can do
 it so cheaply: one integer comparison against scanning the whole
 procarray and taking an LWlock.

[ after reading the patch a bit closer... ]  Actually, it's not as
obvious as all that.  TransactionIdIsInProgress already falls out before
the proposed test for any XID  RecentXmin, which means that in reality
it's fairly probable that the target XID is running.  So while this test
may not cost much, it's not clear that it really buys much either.

I'm going to go ahead and apply it, but it'd be good if someone would
verify that it at least doesn't cost anything on some real benchmarks.

BTW, I think we should put it in front of, not after, the
TransactionIdIsCurrentTransactionId test, since as was just being
discussed that could have nontrivial execution time.  (I'll go look at
Heikki's improvement on that next, but it'll still be not-free if
there's lots of subtransactions.)

regards, tom lane

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] TransactionIdIsInProgress() cache

2008-03-11 Thread Tom Lane
I wrote:
 [ after reading the patch a bit closer... ]  Actually, it's not as
 obvious as all that.  TransactionIdIsInProgress already falls out before
 the proposed test for any XID  RecentXmin, which means that in reality
 it's fairly probable that the target XID is running.  So while this test
 may not cost much, it's not clear that it really buys much either.

I realized that a pretty simple test was already built into the code:
look at the stats gathered by XIDCACHE_DEBUG.  Here are the totals for
a set of parallel regression tests:

xmin:   185668
known:  25728
myxact: 5521
latest: 239
mainxid:484
childxid:   0
nooflo: 3331
slow:   0

So even though the xmin test takes out a lot, this seems worth doing.
Some more-formal performance testing might still be a good idea though.

For completeness, the raw per-backend stats are attached.
Unsurprisingly, the wins come in bunches.

regards, tom lane


XidCache: xmin: 1, known: 0, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 0, slow: 0
XidCache: xmin: 1, known: 0, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 0, slow: 0
XidCache: xmin: 0, known: 0, myxact: 4, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 1, slow: 0
XidCache: xmin: 0, known: 9, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 1, slow: 0
XidCache: xmin: 0, known: 14, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 17, slow: 0
XidCache: xmin: 1, known: 3, myxact: 1, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 3, slow: 0
XidCache: xmin: 0, known: 11, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 11, slow: 0
XidCache: xmin: 18, known: 1, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 1, slow: 0
XidCache: xmin: 0, known: 1, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 7, slow: 0
XidCache: xmin: 0, known: 1, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 7, slow: 0
XidCache: xmin: 0, known: 2, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 7, slow: 0
XidCache: xmin: 0, known: 6, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 8, slow: 0
XidCache: xmin: 32, known: 4, myxact: 2, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 5, slow: 0
XidCache: xmin: 0, known: 1, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 15, slow: 0
XidCache: xmin: 25, known: 2, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 2, slow: 0
XidCache: xmin: 6, known: 5, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 13, slow: 0
XidCache: xmin: 103, known: 2, myxact: 0, latest: 2, mainxid: 0, childxid: 0, 
nooflo: 5, slow: 0
XidCache: xmin: 174, known: 0, myxact: 13, latest: 0, mainxid: 1, childxid: 0, 
nooflo: 7, slow: 0
XidCache: xmin: 94, known: 54, myxact: 1, latest: 2, mainxid: 0, childxid: 0, 
nooflo: 28, slow: 0
XidCache: xmin: 97, known: 89, myxact: 19, latest: 0, mainxid: 2, childxid: 0, 
nooflo: 50, slow: 0
XidCache: xmin: 2401, known: 12, myxact: 17, latest: 2, mainxid: 0, childxid: 
0, nooflo: 16, slow: 0
XidCache: xmin: 156, known: 11, myxact: 15, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 5, slow: 0
XidCache: xmin: 137, known: 6, myxact: 9, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 4, slow: 0
XidCache: xmin: 8, known: 1, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 1, slow: 0
XidCache: xmin: 6, known: 1, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 1, slow: 0
XidCache: xmin: 59, known: 3, myxact: 5, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 1, slow: 0
XidCache: xmin: 7, known: 1, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 5, slow: 0
XidCache: xmin: 0, known: 0, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 0, slow: 0
XidCache: xmin: 43, known: 1, myxact: 7, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 1, slow: 0
XidCache: xmin: 1, known: 3, myxact: 1, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 5, slow: 0
XidCache: xmin: 1, known: 1, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 7, slow: 0
XidCache: xmin: 0, known: 1, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 8, slow: 0
XidCache: xmin: 0, known: 1, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 14, slow: 0
XidCache: xmin: 0, known: 1, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 7, slow: 0
XidCache: xmin: 6, known: 4, myxact: 1, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 19, slow: 0
XidCache: xmin: 0, known: 3, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 11, slow: 0
XidCache: xmin: 12, known: 8, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 14, slow: 0
XidCache: xmin: 0, known: 0, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 0, slow: 0
XidCache: xmin: 42, known: 7, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 35, slow: 0
XidCache: xmin: 15, known: 1, myxact: 0, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 2, slow: 0
XidCache: xmin: 308, known: 8, myxact: 67, latest: 0, mainxid: 0, childxid: 0, 
nooflo: 2, slow: 0
XidCache: xmin: 51, 

Re: [PATCHES] TransactionIdIsInProgress() cache

2008-03-11 Thread Tom Lane
Simon Riggs [EMAIL PROTECTED] writes:
 We currently have a single item cache of the last checked TransactionId,
 which optimises the call to TransactionIdDidCommit() during
 HeapTupleSatisfiesMVCC() and partners.

 Before we call TransactionIdDidCommit() we always call
 TransactionIdIsInProgress().

 TransactionIdIsInProgress() doesn't check the single item cache, so even
 if we have just checked for this xid, we will check it again. Since this
 function takes ProcArrayLock and may be called while holding other locks
 it will improve scalability if we can skip the call, for the cost of an
 integer comparison.

 Following patch implements fastpath in TransactionIdIsInProgress() to
 utilise single item cache.

Applied with minor adjustments and some desultory comment-improvement.

regards, tom lane

-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches


Re: [PATCHES] TransactionIdIsInProgress() cache

2008-03-05 Thread Bruce Momjian

Your patch has been added to the PostgreSQL unapplied patches list at:

http://momjian.postgresql.org/cgi-bin/pgpatches

It will be applied as soon as one of the PostgreSQL committers reviews
and approves it.

---


Simon Riggs wrote:
 We currently have a single item cache of the last checked TransactionId,
 which optimises the call to TransactionIdDidCommit() during
 HeapTupleSatisfiesMVCC() and partners.
 
 Before we call TransactionIdDidCommit() we always call
 TransactionIdIsInProgress().
 
 TransactionIdIsInProgress() doesn't check the single item cache, so even
 if we have just checked for this xid, we will check it again. Since this
 function takes ProcArrayLock and may be called while holding other locks
 it will improve scalability if we can skip the call, for the cost of an
 integer comparison.
 
 Following patch implements fastpath in TransactionIdIsInProgress() to
 utilise single item cache.
 
 -- 
   Simon Riggs
   2ndQuadrant  http://www.2ndQuadrant.com 

[ Attachment, skipping... ]

 
 ---(end of broadcast)---
 TIP 1: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to [EMAIL PROTECTED] so that your
message can get through to the mailing list cleanly

-- 
  Bruce Momjian  [EMAIL PROTECTED]http://momjian.us
  EnterpriseDB http://postgres.enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +

--
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://mail.postgresql.org/mj/mj_wwwusr?domain=postgresql.orgextra=pgsql-patches