There are only four subsystems which require a callback at the beginning of each subtransaction: the relevant functions are AtSubStart_Memory, AtSubStart_ResourceOwner, AtSubStart_Notify, and AfterTriggerBeginSubXact. The AtSubStart_Memory and AtSubStart_ResourceOwner callbacks seem relatively unobjectionable, because almost every subtransaction is going to allocate memory and acquire some resource managed by a resource owner, but the others represent initialization that has to be done whether or not the corresponding feature is used.
Generally, a subsystem can avoid needing a callback at subtransaction start (or transaction start) by detecting new levels of subtransactions at time of use. A typical practice is to maintain a stack which has entries only for those transaction nesting levels where the functionality was used. The attached patch implements this method for async.c. I was a little surprised to find that it makes a pretty noticeable performance difference when starting and ending trivial subtransactions. I used this test case: \timing do $$begin for i in 1 .. 10000000 loop begin null; exception when others then null; end; end loop; end;$$; I ran the test four times with and without the patch and took the median of the last three. This was an attempt to exclude effects due to starting up the database cluster. With the patch, the result was 3127.377 ms; without the patch, it was 3527.285 ms. That's a big enough difference that I'm wondering whether I did something wrong while testing this, so feel free to check my work and tell me whether I'm all wet. Still, I don't find it wholly unbelievable, because I've observed in the past that these code paths are lean enough that a few palloc() calls can make a noticeable difference, and the effect of this patch is to remove a few palloc() calls. -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company
0001-Remove-AtSubStart_Notify.patch
Description: Binary data