On Thu, Dec 17, 2015 at 3:15 AM, Mithun Cy <mithun...@enterprisedb.com>
wrote:

> I have rebased the patch and tried to run pgbench.

> I see memory corruptions, attaching the valgrind report for the same.
Sorry forgot to add re-based patch, adding the same now.
After some analysis I saw writing to shared memory to store shared snapshot
is not protected under exclusive write lock, this leads to memory
corruptions.
I think until this is fixed measuring the performance will not be much
useful.
-- 
Thanks and Regards
Mithun C Y
EnterpriseDB: http://www.enterprisedb.com
*** a/src/backend/commands/cluster.c
--- b/src/backend/commands/cluster.c
***************
*** 1559,1564 **** finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
--- 1559,1565 ----
  			elog(ERROR, "cache lookup failed for relation %u", OIDOldHeap);
  		relform = (Form_pg_class) GETSTRUCT(reltup);
  
+ 		Assert(TransactionIdIsNormal(frozenXid));
  		relform->relfrozenxid = frozenXid;
  		relform->relminmxid = cutoffMulti;
  
*** a/src/backend/storage/ipc/procarray.c
--- b/src/backend/storage/ipc/procarray.c
***************
*** 410,415 **** ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
--- 410,416 ----
  		if (LWLockConditionalAcquire(ProcArrayLock, LW_EXCLUSIVE))
  		{
  			ProcArrayEndTransactionInternal(proc, pgxact, latestXid);
+                         ProcGlobal->cached_snapshot_valid = false;
  			LWLockRelease(ProcArrayLock);
  		}
  		else
***************
*** 558,563 **** ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
--- 559,566 ----
  		nextidx = pg_atomic_read_u32(&proc->nextClearXidElem);
  	}
  
+         ProcGlobal->cached_snapshot_valid = false;
+ 
  	/* We're done with the lock now. */
  	LWLockRelease(ProcArrayLock);
  
***************
*** 1543,1548 **** GetSnapshotData(Snapshot snapshot)
--- 1546,1553 ----
  					 errmsg("out of memory")));
  	}
  
+         snapshot->takenDuringRecovery = RecoveryInProgress();
+ 
  	/*
  	 * It is sufficient to get shared lock on ProcArrayLock, even if we are
  	 * going to set MyPgXact->xmin.
***************
*** 1557,1565 **** GetSnapshotData(Snapshot snapshot)
  	/* initialize xmin calculation with xmax */
  	globalxmin = xmin = xmax;
  
! 	snapshot->takenDuringRecovery = RecoveryInProgress();
  
! 	if (!snapshot->takenDuringRecovery)
  	{
  		int		   *pgprocnos = arrayP->pgprocnos;
  		int			numProcs;
--- 1562,1592 ----
  	/* initialize xmin calculation with xmax */
  	globalxmin = xmin = xmax;
  
! 	if (!snapshot->takenDuringRecovery && ProcGlobal->cached_snapshot_valid)
! 	{
! 		Snapshot csnap = &ProcGlobal->cached_snapshot;
! 		TransactionId *saved_xip;
! 		TransactionId *saved_subxip;
  
! 		saved_xip = snapshot->xip;
! 		saved_subxip = snapshot->subxip;
! 
! 		memcpy(snapshot, csnap, sizeof(SnapshotData));
! 
! 		snapshot->xip = saved_xip;
! 		snapshot->subxip = saved_subxip;
! 
! 		memcpy(snapshot->xip, csnap->xip,
! 			   sizeof(TransactionId) * csnap->xcnt);
! 		memcpy(snapshot->subxip, csnap->subxip,
! 			   sizeof(TransactionId) * csnap->subxcnt);
! 		globalxmin = ProcGlobal->cached_snapshot_globalxmin;
! 		xmin = csnap->xmin;
! 
! 		Assert(TransactionIdIsValid(globalxmin));
! 		Assert(TransactionIdIsValid(xmin));
! 	}
! 	else if (!snapshot->takenDuringRecovery)
  	{
  		int		   *pgprocnos = arrayP->pgprocnos;
  		int			numProcs;
***************
*** 1577,1591 **** GetSnapshotData(Snapshot snapshot)
  			TransactionId xid;
  
  			/*
! 			 * Backend is doing logical decoding which manages xmin
! 			 * separately, check below.
  			 */
! 			if (pgxact->vacuumFlags & PROC_IN_LOGICAL_DECODING)
! 				continue;
! 
! 			/* Ignore procs running LAZY VACUUM */
! 			if (pgxact->vacuumFlags & PROC_IN_VACUUM)
! 				continue;
  
  			/* Update globalxmin to be the smallest valid xmin */
  			xid = pgxact->xmin; /* fetch just once */
--- 1604,1615 ----
  			TransactionId xid;
  
  			/*
! 			 * Ignore procs running LAZY VACUUM (which don't need to retain
! 			 * rows) and backends doing logical decoding (which manages xmin
! 			 * separately, check below).
  			 */
! 			if (pgxact->vacuumFlags & (PROC_IN_LOGICAL_DECODING | PROC_IN_VACUUM))
!                                 continue;
  
  			/* Update globalxmin to be the smallest valid xmin */
  			xid = pgxact->xmin; /* fetch just once */
***************
*** 1653,1658 **** GetSnapshotData(Snapshot snapshot)
--- 1677,1706 ----
  				}
  			}
  		}
+ 
+ 		/* upate cache */
+ 		{
+ 			Snapshot csnap = &ProcGlobal->cached_snapshot;
+ 			TransactionId *saved_xip;
+ 			TransactionId *saved_subxip;
+ 
+ 			ProcGlobal->cached_snapshot_globalxmin = globalxmin;
+ 
+ 			saved_xip = csnap->xip;
+ 			saved_subxip = csnap->subxip;
+ 			memcpy(csnap, snapshot, sizeof(SnapshotData));
+ 			csnap->xip = saved_xip;
+ 			csnap->subxip = saved_subxip;
+ 
+ 			/* not yet stored. Yuck */
+ 			csnap->xmin = xmin;
+ 
+ 			memcpy(csnap->xip, snapshot->xip,
+ 				   sizeof(TransactionId) * csnap->xcnt);
+ 			memcpy(csnap->subxip, snapshot->subxip,
+ 				   sizeof(TransactionId) * csnap->subxcnt);
+ 			ProcGlobal->cached_snapshot_valid = true;
+ 		}
  	}
  	else
  	{
*** a/src/backend/storage/lmgr/proc.c
--- b/src/backend/storage/lmgr/proc.c
***************
*** 114,119 **** ProcGlobalShmemSize(void)
--- 114,126 ----
  	size = add_size(size, mul_size(NUM_AUXILIARY_PROCS, sizeof(PGXACT)));
  	size = add_size(size, mul_size(max_prepared_xacts, sizeof(PGXACT)));
  
+ 	/* for the cached snapshot */
+ #define PROCARRAY_MAXPROCS	(MaxBackends + max_prepared_xacts)
+ 	size = add_size(size, mul_size(sizeof(TransactionId), PROCARRAY_MAXPROCS));
+ #define TOTAL_MAX_CACHED_SUBXIDS \
+ 	((PGPROC_MAX_CACHED_SUBXIDS + 1) * PROCARRAY_MAXPROCS)
+ 	size = add_size(size, mul_size(sizeof(TransactionId), TOTAL_MAX_CACHED_SUBXIDS));
+ 
  	return size;
  }
  
***************
*** 275,280 **** InitProcGlobal(void)
--- 282,293 ----
  	/* Create ProcStructLock spinlock, too */
  	ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
  	SpinLockInit(ProcStructLock);
+ 
+ 	/* cached snapshot */
+ 	ProcGlobal->cached_snapshot_valid = false;
+ 	ProcGlobal->cached_snapshot.xip = ShmemAlloc(PROCARRAY_MAXPROCS * sizeof(TransactionId));
+ 	ProcGlobal->cached_snapshot.subxip = ShmemAlloc(TOTAL_MAX_CACHED_SUBXIDS * sizeof(TransactionId));
+ 	ProcGlobal->cached_snapshot_globalxmin = InvalidTransactionId;
  }
  
  /*
*** a/src/include/storage/proc.h
--- b/src/include/storage/proc.h
***************
*** 16,21 ****
--- 16,22 ----
  
  #include "access/xlogdefs.h"
  #include "lib/ilist.h"
+ #include "utils/snapshot.h"
  #include "storage/latch.h"
  #include "storage/lock.h"
  #include "storage/pg_sema.h"
***************
*** 220,225 **** typedef struct PROC_HDR
--- 221,231 ----
  	int			startupProcPid;
  	/* Buffer id of the buffer that Startup process waits for pin on, or -1 */
  	int			startupBufferPinWaitBufId;
+ 
+ 	/* Cached snapshot */
+ 	bool		cached_snapshot_valid;
+ 	SnapshotData cached_snapshot;
+ 	TransactionId cached_snapshot_globalxmin;
  } PROC_HDR;
  
  extern PROC_HDR *ProcGlobal;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to