diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index a7e8cf2..4d7debe 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -366,11 +366,13 @@ ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
 					(arrayP->numProcs - index - 1) * sizeof(int));
 			arrayP->pgprocnos[arrayP->numProcs - 1] = -1;	/* for debugging */
 			arrayP->numProcs--;
+			ProcGlobal->is_snapshot_valid = false;
 			LWLockRelease(ProcArrayLock);
 			return;
 		}
 	}
 
+	ProcGlobal->is_snapshot_valid = false;
 	/* Oops */
 	LWLockRelease(ProcArrayLock);
 
@@ -414,6 +416,7 @@ ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid)
 		if (LWLockConditionalAcquire(ProcArrayLock, LW_EXCLUSIVE))
 		{
 			ProcArrayEndTransactionInternal(proc, pgxact, latestXid);
+			ProcGlobal->is_snapshot_valid = false;
 			LWLockRelease(ProcArrayLock);
 		}
 		else
@@ -565,6 +568,8 @@ ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
 		nextidx = pg_atomic_read_u32(&proc->procArrayGroupNext);
 	}
 
+	ProcGlobal->is_snapshot_valid = false;
+
 	/* We're done with the lock now. */
 	LWLockRelease(ProcArrayLock);
 
@@ -1552,6 +1557,8 @@ GetSnapshotData(Snapshot snapshot)
 					 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.
@@ -1566,100 +1573,200 @@ GetSnapshotData(Snapshot snapshot)
 	/* initialize xmin calculation with xmax */
 	globalxmin = xmin = xmax;
 
-	snapshot->takenDuringRecovery = RecoveryInProgress();
-
 	if (!snapshot->takenDuringRecovery)
 	{
-		int		   *pgprocnos = arrayP->pgprocnos;
-		int			numProcs;
+		if (ProcGlobal->is_snapshot_valid)
+		{
+			Snapshot	csnap = &ProcGlobal->cached_snapshot;
+			TransactionId *saved_xip;
+			TransactionId *saved_subxip;
 
-		/*
-		 * Spin over procArray checking xid, xmin, and subxids.  The goal is
-		 * to gather all active xids, find the lowest xmin, and try to record
-		 * subxids.
-		 */
-		numProcs = arrayP->numProcs;
-		for (index = 0; index < numProcs; index++)
+			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;
+
+			count = csnap->xcnt;
+			subcount = csnap->subxcnt;
+			suboverflowed = csnap->suboverflowed;
+
+			Assert(TransactionIdIsValid(globalxmin));
+			Assert(TransactionIdIsValid(xmin));
+		}
+		else					/* compute snapshot. */
 		{
-			int			pgprocno = pgprocnos[index];
-			volatile PGXACT *pgxact = &allPgXact[pgprocno];
-			TransactionId xid;
+			int		   *pgprocnos = arrayP->pgprocnos;
+			int			numProcs;
 
 			/*
-			 * Backend is doing logical decoding which manages xmin
-			 * separately, check below.
+			 * Spin over procArray checking xid, xmin, and subxids.  The goal
+			 * is to gather all active xids, find the lowest xmin, and try to
+			 * record subxids.
 			 */
-			if (pgxact->vacuumFlags & PROC_IN_LOGICAL_DECODING)
-				continue;
+			numProcs = arrayP->numProcs;
+			for (index = 0; index < numProcs; index++)
+			{
+				int			pgprocno = pgprocnos[index];
+				volatile PGXACT *pgxact = &allPgXact[pgprocno];
+				TransactionId xid;
 
-			/* Ignore procs running LAZY VACUUM */
-			if (pgxact->vacuumFlags & PROC_IN_VACUUM)
-				continue;
+				/*
+				 * Backend is doing logical decoding which manages xmin
+				 * separately, check below.
+				 */
+				if (pgxact->vacuumFlags & PROC_IN_LOGICAL_DECODING)
+					continue;
 
-			/* Update globalxmin to be the smallest valid xmin */
-			xid = pgxact->xmin; /* fetch just once */
-			if (TransactionIdIsNormal(xid) &&
-				NormalTransactionIdPrecedes(xid, globalxmin))
-				globalxmin = xid;
+				/* Ignore procs running LAZY VACUUM */
+				if (pgxact->vacuumFlags & PROC_IN_VACUUM)
+					continue;
 
-			/* Fetch xid just once - see GetNewTransactionId */
-			xid = pgxact->xid;
+				/* Update globalxmin to be the smallest valid xmin */
+				xid = pgxact->xmin; /* fetch just once */
+				if (TransactionIdIsNormal(xid) &&
+					NormalTransactionIdPrecedes(xid, globalxmin))
+					globalxmin = xid;
 
-			/*
-			 * If the transaction has no XID assigned, we can skip it; it
-			 * won't have sub-XIDs either.  If the XID is >= xmax, we can also
-			 * skip it; such transactions will be treated as running anyway
-			 * (and any sub-XIDs will also be >= xmax).
-			 */
-			if (!TransactionIdIsNormal(xid)
-				|| !NormalTransactionIdPrecedes(xid, xmax))
-				continue;
+				/* Fetch xid just once - see GetNewTransactionId */
+				xid = pgxact->xid;
 
-			/*
-			 * We don't include our own XIDs (if any) in the snapshot, but we
-			 * must include them in xmin.
-			 */
-			if (NormalTransactionIdPrecedes(xid, xmin))
-				xmin = xid;
-			if (pgxact == MyPgXact)
-				continue;
+				/*
+				 * If the transaction has no XID assigned, we can skip it; it
+				 * won't have sub-XIDs either.  If the XID is >= xmax, we can
+				 * also skip it; such transactions will be treated as running
+				 * anyway (and any sub-XIDs will also be >= xmax).
+				 */
+				if (!TransactionIdIsNormal(xid)
+					|| !NormalTransactionIdPrecedes(xid, xmax))
+					continue;
+
+				/*
+				 * We don't include our own XIDs (if any) in the snapshot, but
+				 * we must include them in xmin.
+				 */
+				if (NormalTransactionIdPrecedes(xid, xmin))
+					xmin = xid;
+				if (pgxact == MyPgXact)
+					continue;
 
-			/* Add XID to snapshot. */
-			snapshot->xip[count++] = xid;
+				/* Add XID to snapshot. */
+				snapshot->xip[count++] = xid;
+
+				/*
+				 * Save subtransaction XIDs if possible (if we've already
+				 * overflowed, there's no point).  Note that the subxact XIDs
+				 * must be later than their parent, so no need to check them
+				 * against xmin.  We could filter against xmax, but it seems
+				 * better not to do that much work while holding the
+				 * ProcArrayLock.
+				 *
+				 * The other backend can add more subxids concurrently, but
+				 * cannot remove any.  Hence it's important to fetch nxids
+				 * just once. Should be safe to use memcpy, though.  (We
+				 * needn't worry about missing any xids added concurrently,
+				 * because they must postdate xmax.)
+				 *
+				 * Again, our own XIDs are not included in the snapshot.
+				 */
+				if (!suboverflowed)
+				{
+					if (pgxact->overflowed)
+						suboverflowed = true;
+					else
+					{
+						int			nxids = pgxact->nxids;
+
+						if (nxids > 0)
+						{
+							volatile PGPROC *proc = &allProcs[pgprocno];
+
+							memcpy(snapshot->subxip + subcount,
+								   (void *) proc->subxids.xids,
+								   nxids * sizeof(TransactionId));
+							subcount += nxids;
+						}
+					}
+				}
+			}
 
 			/*
-			 * Save subtransaction XIDs if possible (if we've already
-			 * overflowed, there's no point).  Note that the subxact XIDs must
-			 * be later than their parent, so no need to check them against
-			 * xmin.  We could filter against xmax, but it seems better not to
-			 * do that much work while holding the ProcArrayLock.
-			 *
-			 * The other backend can add more subxids concurrently, but cannot
-			 * remove any.  Hence it's important to fetch nxids just once.
-			 * Should be safe to use memcpy, though.  (We needn't worry about
-			 * missing any xids added concurrently, because they must postdate
-			 * xmax.)
-			 *
-			 * Again, our own XIDs are not included in the snapshot.
+			 * Let only one of the caller cache the computed snapshot, and
+			 * others can continue as before.
 			 */
-			if (!suboverflowed)
+			if (!ProcGlobal->is_snapshot_valid &&
+				LWLockConditionalAcquire(&ProcGlobal->CachedSnapshotLock,
+										 LW_EXCLUSIVE))
 			{
-				if (pgxact->overflowed)
-					suboverflowed = true;
-				else
+				Snapshot	csnap = &ProcGlobal->cached_snapshot;
+				TransactionId *saved_xip;
+				TransactionId *saved_subxip;
+				int			curr_subcount = subcount;
+
+				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;
+
+				csnap->xmin = xmin;
+
+				memcpy(csnap->xip, snapshot->xip,
+					   sizeof(TransactionId) * count);
+				memcpy(csnap->subxip, snapshot->subxip,
+					   sizeof(TransactionId) * subcount);
+
+				/* Add my own XID and sub-XIDs to snapshot. */
+				if (TransactionIdIsNormal(MyPgXact->xid)
+					&& NormalTransactionIdPrecedes(MyPgXact->xid, xmax))
 				{
-					int			nxids = pgxact->nxids;
 
-					if (nxids > 0)
-					{
-						volatile PGPROC *proc = &allProcs[pgprocno];
+					csnap->xip[count] = MyPgXact->xid;
+					csnap->xcnt = count + 1;
 
-						memcpy(snapshot->subxip + subcount,
-							   (void *) proc->subxids.xids,
-							   nxids * sizeof(TransactionId));
-						subcount += nxids;
+					if (!suboverflowed)
+					{
+						if (MyPgXact->overflowed)
+							suboverflowed = true;
+						else
+						{
+							int			nxids = MyPgXact->nxids;
+
+							if (nxids > 0)
+							{
+								memcpy(csnap->subxip + subcount,
+									   (void *) MyProc->subxids.xids,
+									   nxids * sizeof(TransactionId));
+								curr_subcount += nxids;
+							}
+						}
 					}
+
 				}
+				else
+					csnap->xcnt = count;
+
+				csnap->subxcnt = curr_subcount;
+				csnap->suboverflowed = suboverflowed;
+
+				/*
+				 * The memory barrier has be to be placed here to ensure that
+				 * is_snapshot_valid is set only after snapshot is cached.
+				 */
+				pg_write_barrier();
+				ProcGlobal->is_snapshot_valid = true;
+				LWLockRelease(&ProcGlobal->CachedSnapshotLock);
 			}
 		}
 	}
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index bfa8499..e67fd60 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -118,6 +118,13 @@ ProcGlobalShmemSize(void)
 	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;
 }
 
@@ -278,6 +285,15 @@ InitProcGlobal(void)
 	/* Create ProcStructLock spinlock, too */
 	ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
 	SpinLockInit(ProcStructLock);
+
+	/* Initialize structure for cached snapshot */
+	ProcGlobal->is_snapshot_valid = false;
+	LWLockInitialize(&ProcGlobal->CachedSnapshotLock, LWTRANCHE_PROC);
+	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;
 }
 
 /*
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 7dbaa81..7d06904 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -16,6 +16,7 @@
 
 #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"
@@ -253,6 +254,22 @@ typedef struct PROC_HDR
 	int			startupProcPid;
 	/* Buffer id of the buffer that Startup process waits for pin on, or -1 */
 	int			startupBufferPinWaitBufId;
+
+	/*
+	 * In GetSnapshotData we can reuse the previously snapshot computed if no
+	 * new transaction has committed or rolledback. Thus saving good amount of
+	 * computation cycle under GetSnapshotData where we need to iterate
+	 * through procArray every time we try to get the current snapshot. Below
+	 * members help us to save the previously computed snapshot in global
+	 * shared memory and any process which want to get current snapshot can
+	 * directly copy from them if it is still valid.
+	 */
+	SnapshotData cached_snapshot;	/* Previously saved snapshot */
+	volatile bool is_snapshot_valid;	/* is above snapshot valid */
+	TransactionId cached_snapshot_globalxmin;	/* globalxmin when above
+												 * snapshot was computed */
+	LWLock		CachedSnapshotLock; /* A try lock to make sure only one
+									 * process write to cached_snapshot */
 } PROC_HDR;
 
 extern PROC_HDR *ProcGlobal;
