counting pallocs

Started by Robert Haasover 13 years ago4 messages
#1Robert Haas
robertmhaas@gmail.com
1 attachment(s)

The attached patch provides some rough instrumentation for determining
where palloc calls are coming from. This is obviously just for
noodling around with, not for commit, and there may well be bugs. But
enjoy.

I gave this a quick spin on a couple of test workloads: a very short
pgbench test, a very short pgbench -S test, and the regression tests.
On the pgbench test, the top culprits are ExecInitExpr() and
expression_tree_mutator(); in both cases, the lappend() call for the
T_List case is the major contributor. Other significant contributors
include _copyVar(), which I haven't drilled into terribly far but
seems to be coming mostly from add_vars_to_targetlist();
buildRelationAliases() via lappend, pstrdup, and makeString;
ExecAllocTupleTableSlot(); and makeColumnRef() via makeNode, lcons,
and makeString.

The pgbench -S results are similar, but build_physical_tlist() also
pops up fairly high.

On the regression tests, heap_tuple_untoast_attr() is at the very top
of the list, and specifically for the VARATT_IS_SHORT() case. It
might be good to disaggregate this some more, but I'm too tired for
that right now. index_form_tuple()'s palloc0 call comes in second,
and heap_form_minimal_tuple()'s palloc0 is third.
LockAcquireExtended()'s allocation of a new LOCALLOCK entry also comes
in prettyhigh; ExecInitExpr() shows up here too; and heap_form_tuple()
shows up as well.

One piece of reasonably low-hanging fruit appears to be OpExpr. It
seems like it would be better all around to put Node *arg1 and Node
*arg2 in there instead of a list... aside from saving pallocs, it
seems like it would generally simplify the code.

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

Attachments:

count-pallocs.patchapplication/octet-stream; name=count-pallocs.patchDownload
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 607a80d..ca357e3 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -288,7 +288,8 @@ initialize_reloptions(void)
 	if (relOpts)
 		pfree(relOpts);
 	relOpts = MemoryContextAlloc(TopMemoryContext,
-								 (j + 1) * sizeof(relopt_gen *));
+								 (j + 1) * sizeof(relopt_gen *),
+								 FileAndLineTag());
 
 	j = 0;
 	for (i = 0; boolRelOpts[i].gen.name; i++)
diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c
index 988896d..494d980 100644
--- a/src/backend/access/gist/gistbuild.c
+++ b/src/backend/access/gist/gistbuild.c
@@ -595,7 +595,8 @@ gistProcessItup(GISTBuildState *buildstate, IndexTuple itup,
 		/* Create new path item representing current page */
 		parent = path;
 		path = (GISTBufferingInsertStack *) MemoryContextAlloc(gfbb->context,
-										   sizeof(GISTBufferingInsertStack));
+										   sizeof(GISTBufferingInsertStack),
+										   FileAndLineTag());
 		path->parent = parent;
 		path->level = parent->level - 1;
 		path->blkno = childblkno;
@@ -684,7 +685,8 @@ gistbufferinginserttuples(GISTBuildState *buildstate, Buffer buffer,
 		BlockNumber leftmostchild;
 
 		gfbb->rootitem = (GISTBufferingInsertStack *) MemoryContextAlloc(
-							gfbb->context, sizeof(GISTBufferingInsertStack));
+							gfbb->context, sizeof(GISTBufferingInsertStack),
+							FileAndLineTag());
 		gfbb->rootitem->parent = NULL;
 		gfbb->rootitem->blkno = GIST_ROOT_BLKNO;
 		gfbb->rootitem->downlinkoffnum = InvalidOffsetNumber;
@@ -828,7 +830,8 @@ gistBufferingFindCorrectParent(GISTBuildState *buildstate,
 		if (!copied)
 		{
 			parent = (GISTBufferingInsertStack *) MemoryContextAlloc(gfbb->context,
-										   sizeof(GISTBufferingInsertStack));
+										   sizeof(GISTBufferingInsertStack),
+										   FileAndLineTag());
 			memcpy(parent, child->parent, sizeof(GISTBufferingInsertStack));
 			if (parent->parent)
 				parent->parent->refCount++;
diff --git a/src/backend/access/gist/gistbuildbuffers.c b/src/backend/access/gist/gistbuildbuffers.c
index 34a12bc..fc0c52f 100644
--- a/src/backend/access/gist/gistbuildbuffers.c
+++ b/src/backend/access/gist/gistbuildbuffers.c
@@ -111,7 +111,8 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
 	 * Root path item of the tree. Updated on each root node split.
 	 */
 	gfbb->rootitem = (GISTBufferingInsertStack *) MemoryContextAlloc(
-							gfbb->context, sizeof(GISTBufferingInsertStack));
+							gfbb->context, sizeof(GISTBufferingInsertStack),
+							FileAndLineTag());
 	gfbb->rootitem->parent = NULL;
 	gfbb->rootitem->blkno = GIST_ROOT_BLKNO;
 	gfbb->rootitem->downlinkoffnum = InvalidOffsetNumber;
@@ -235,7 +236,8 @@ gistAllocateNewPageBuffer(GISTBuildBuffers *gfbb)
 	GISTNodeBufferPage *pageBuffer;
 
 	pageBuffer = (GISTNodeBufferPage *) MemoryContextAlloc(gfbb->context,
-														   BLCKSZ);
+														   BLCKSZ,
+														   FileAndLineTag());
 	pageBuffer->prev = InvalidBlockNumber;
 
 	/* Set page free space */
diff --git a/src/backend/access/hash/hashscan.c b/src/backend/access/hash/hashscan.c
index 0f34a3d..8ea6555 100644
--- a/src/backend/access/hash/hashscan.c
+++ b/src/backend/access/hash/hashscan.c
@@ -95,7 +95,8 @@ _hash_regscan(IndexScanDesc scan)
 	HashScanList new_el;
 
 	new_el = (HashScanList) MemoryContextAlloc(TopMemoryContext,
-											   sizeof(HashScanListData));
+											   sizeof(HashScanListData),
+											   FileAndLineTag());
 	new_el->hashsl_scan = scan;
 	new_el->hashsl_owner = CurrentResourceOwner;
 	new_el->hashsl_next = HashScans;
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index c5e147f..18af76a 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -275,7 +275,8 @@ _bt_getroot(Relation rel, int access)
 		 * Cache the metapage data for next time
 		 */
 		rel->rd_amcache = MemoryContextAlloc(rel->rd_indexcxt,
-											 sizeof(BTMetaPageData));
+											 sizeof(BTMetaPageData),
+											 FileAndLineTag());
 		memcpy(rel->rd_amcache, metad, sizeof(BTMetaPageData));
 
 		/*
diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c
index 46a10f6..a39548d 100644
--- a/src/backend/access/spgist/spgutils.c
+++ b/src/backend/access/spgist/spgutils.c
@@ -52,7 +52,7 @@ spgGetCache(Relation index)
 		SpGistMetaPageData *metadata;
 
 		cache = MemoryContextAllocZero(index->rd_indexcxt,
-									   sizeof(SpGistCache));
+									   sizeof(SpGistCache), FileAndLineTag());
 
 		/* SPGiST doesn't support multi-column indexes */
 		Assert(index->rd_att->natts == 1);
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 8bdf387..2507ce9 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -1207,7 +1207,7 @@ mXactCachePut(MultiXactId multi, int nxids, TransactionId *xids)
 	entry = (mXactCacheEnt *)
 		MemoryContextAlloc(MXactContext,
 						   offsetof(mXactCacheEnt, xids) +
-						   nxids * sizeof(TransactionId));
+						   nxids * sizeof(TransactionId), FileAndLineTag());
 
 	entry->multi = multi;
 	entry->nxids = nxids;
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index c71a10e..d35f5bc 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -1328,7 +1328,8 @@ AtSubCommit_childXids(void)
 		if (s->parent->childXids == NULL)
 			new_childXids =
 				MemoryContextAlloc(TopTransactionContext,
-								   new_maxChildXids * sizeof(TransactionId));
+								   new_maxChildXids * sizeof(TransactionId),
+								   FileAndLineTag());
 		else
 			new_childXids = repalloc(s->parent->childXids,
 								   new_maxChildXids * sizeof(TransactionId));
@@ -3034,7 +3035,8 @@ RegisterXactCallback(XactCallback callback, void *arg)
 	XactCallbackItem *item;
 
 	item = (XactCallbackItem *)
-		MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
+		MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem),
+						   FileAndLineTag());
 	item->callback = callback;
 	item->arg = arg;
 	item->next = Xact_callbacks;
@@ -3089,7 +3091,8 @@ RegisterSubXactCallback(SubXactCallback callback, void *arg)
 	SubXactCallbackItem *item;
 
 	item = (SubXactCallbackItem *)
-		MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
+		MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem),
+						   FileAndLineTag());
 	item->callback = callback;
 	item->arg = arg;
 	item->next = SubXact_callbacks;
@@ -4298,7 +4301,8 @@ PushTransaction(void)
 	 */
 	s = (TransactionState)
 		MemoryContextAllocZero(TopTransactionContext,
-							   sizeof(TransactionStateData));
+							   sizeof(TransactionStateData),
+							   FileAndLineTag());
 
 	/*
 	 * Assign a subtransaction ID, watching out for counter wraparound.
diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c
index a017101..d17e66e 100644
--- a/src/backend/catalog/storage.c
+++ b/src/backend/catalog/storage.c
@@ -130,7 +130,8 @@ RelationCreateStorage(RelFileNode rnode, char relpersistence)
 
 	/* Add the relation to the list of stuff to delete at abort */
 	pending = (PendingRelDelete *)
-		MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
+		MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete),
+						   FileAndLineTag());
 	pending->relnode = rnode;
 	pending->backend = backend;
 	pending->atCommit = false;	/* delete if abort */
@@ -173,7 +174,8 @@ RelationDropStorage(Relation rel)
 
 	/* Add the relation to the list of stuff to delete at commit */
 	pending = (PendingRelDelete *)
-		MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
+		MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete),
+						   FileAndLineTag());
 	pending->relnode = rel->rd_node;
 	pending->backend = rel->rd_backend;
 	pending->atCommit = true;	/* delete if commit */
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index 708bebb..12afd94 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -1324,7 +1324,8 @@ PrepareTempTablespaces(void)
 
 	/* Store tablespace OIDs in an array in TopTransactionContext */
 	tblSpcs = (Oid *) MemoryContextAlloc(TopTransactionContext,
-										 list_length(namelist) * sizeof(Oid));
+										 list_length(namelist) * sizeof(Oid),
+										 FileAndLineTag());
 	numSpcs = 0;
 	foreach(l, namelist)
 	{
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 1218d03..97482d0 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -3171,7 +3171,8 @@ afterTriggerAddEvent(AfterTriggerEventList *events,
 				chunksize /= 2; /* too many shared records */
 			chunksize = Min(chunksize, MAX_CHUNK_SIZE);
 		}
-		chunk = MemoryContextAlloc(afterTriggers->event_cxt, chunksize);
+		chunk = MemoryContextAlloc(afterTriggers->event_cxt, chunksize,
+								   FileAndLineTag());
 		chunk->next = NULL;
 		chunk->freeptr = CHUNK_DATA_START(chunk);
 		chunk->endptr = chunk->endfree = (char *) chunk + chunksize;
@@ -3635,7 +3636,7 @@ AfterTriggerBeginXact(void)
 	 */
 	afterTriggers = (AfterTriggers)
 		MemoryContextAlloc(TopTransactionContext,
-						   sizeof(AfterTriggersData));
+						   sizeof(AfterTriggersData), FileAndLineTag());
 
 	afterTriggers->firing_counter = (CommandId) 1;		/* mustn't be 0 */
 	afterTriggers->state = SetConstraintStateCreate(8);
@@ -3647,7 +3648,7 @@ AfterTriggerBeginXact(void)
 	/* We initialize the query stack to a reasonable size */
 	afterTriggers->query_stack = (AfterTriggerEventList *)
 		MemoryContextAlloc(TopTransactionContext,
-						   8 * sizeof(AfterTriggerEventList));
+						   8 * sizeof(AfterTriggerEventList), FileAndLineTag());
 	afterTriggers->maxquerydepth = 8;
 
 	/* Context for events is created only when needed */
@@ -4050,7 +4051,8 @@ SetConstraintStateCreate(int numalloc)
 	state = (SetConstraintState)
 		MemoryContextAllocZero(TopTransactionContext,
 							   sizeof(SetConstraintStateData) +
-						   (numalloc - 1) *sizeof(SetConstraintTriggerData));
+						   (numalloc - 1) *sizeof(SetConstraintTriggerData),
+							FileAndLineTag());
 
 	state->numalloc = numalloc;
 
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index bd7973e..096eb85 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -288,7 +288,8 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
 	nbuckets = Min(nbuckets, (long) ((work_mem * 1024L) / entrysize));
 
 	hashtable = (TupleHashTable) MemoryContextAlloc(tablecxt,
-												 sizeof(TupleHashTableData));
+												 sizeof(TupleHashTableData),
+												 FileAndLineTag());
 
 	hashtable->numCols = numCols;
 	hashtable->keyColIdx = keyColIdx;
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index e755e7c..81fc248 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -281,9 +281,11 @@ ExecSetSlotDescriptor(TupleTableSlot *slot,		/* slot to change */
 	 * the same lifetime as the slot, so allocate in the slot's own context.
 	 */
 	slot->tts_values = (Datum *)
-		MemoryContextAlloc(slot->tts_mcxt, tupdesc->natts * sizeof(Datum));
+		MemoryContextAlloc(slot->tts_mcxt, tupdesc->natts * sizeof(Datum),
+						   FileAndLineTag());
 	slot->tts_isnull = (bool *)
-		MemoryContextAlloc(slot->tts_mcxt, tupdesc->natts * sizeof(bool));
+		MemoryContextAlloc(slot->tts_mcxt, tupdesc->natts * sizeof(bool),
+						   FileAndLineTag());
 }
 
 /* --------------------------------
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 40cd5ce..7eb41b4 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -1404,7 +1404,7 @@ RegisterExprContextCallback(ExprContext *econtext,
 	/* Save the info in appropriate memory context */
 	ecxt_callback = (ExprContext_CB *)
 		MemoryContextAlloc(econtext->ecxt_per_query_memory,
-						   sizeof(ExprContext_CB));
+						   sizeof(ExprContext_CB), FileAndLineTag());
 
 	ecxt_callback->function = function;
 	ecxt_callback->arg = arg;
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index cabe663..7455276 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -715,7 +715,8 @@ ExecHashTableInsert(HashJoinTable hashtable,
 		/* Create the HashJoinTuple */
 		hashTupleSize = HJTUPLE_OVERHEAD + tuple->t_len;
 		hashTuple = (HashJoinTuple) MemoryContextAlloc(hashtable->batchCxt,
-													   hashTupleSize);
+													   hashTupleSize,
+													   FileAndLineTag());
 		hashTuple->hashvalue = hashvalue;
 		memcpy(HJTUPLE_MINTUPLE(hashTuple), tuple, tuple->t_len);
 
@@ -1200,10 +1201,11 @@ ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, int mcvsToUse)
 		 */
 		hashtable->skewBucket = (HashSkewBucket **)
 			MemoryContextAllocZero(hashtable->batchCxt,
-								   nbuckets * sizeof(HashSkewBucket *));
+								   nbuckets * sizeof(HashSkewBucket *),
+								   FileAndLineTag());
 		hashtable->skewBucketNums = (int *)
 			MemoryContextAllocZero(hashtable->batchCxt,
-								   mcvsToUse * sizeof(int));
+								   mcvsToUse * sizeof(int), FileAndLineTag());
 
 		hashtable->spaceUsed += nbuckets * sizeof(HashSkewBucket *)
 			+ mcvsToUse * sizeof(int);
@@ -1252,7 +1254,7 @@ ExecHashBuildSkewHash(HashJoinTable hashtable, Hash *node, int mcvsToUse)
 			/* Okay, create a new skew bucket for this hashvalue. */
 			hashtable->skewBucket[bucket] = (HashSkewBucket *)
 				MemoryContextAlloc(hashtable->batchCxt,
-								   sizeof(HashSkewBucket));
+								   sizeof(HashSkewBucket), FileAndLineTag());
 			hashtable->skewBucket[bucket]->hashvalue = hashvalue;
 			hashtable->skewBucket[bucket]->tuples = NULL;
 			hashtable->skewBucketNums[hashtable->nSkewBuckets] = bucket;
@@ -1336,7 +1338,8 @@ ExecHashSkewTableInsert(HashJoinTable hashtable,
 	/* Create the HashJoinTuple */
 	hashTupleSize = HJTUPLE_OVERHEAD + tuple->t_len;
 	hashTuple = (HashJoinTuple) MemoryContextAlloc(hashtable->batchCxt,
-												   hashTupleSize);
+												   hashTupleSize,
+												   FileAndLineTag());
 	hashTuple->hashvalue = hashvalue;
 	memcpy(HJTUPLE_MINTUPLE(hashTuple), tuple, tuple->t_len);
 	HeapTupleHeaderClearMatch(HJTUPLE_MINTUPLE(hashTuple));
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index ce89ff2..8073fd7 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -1980,7 +1980,8 @@ WinGetPartitionLocalMemory(WindowObject winobj, Size sz)
 	Assert(WindowObjectIsValid(winobj));
 	if (winobj->localmem == NULL)
 		winobj->localmem =
-			MemoryContextAllocZero(winobj->winstate->partcontext, sz);
+			MemoryContextAllocZero(winobj->winstate->partcontext, sz,
+								   FileAndLineTag());
 	return winobj->localmem;
 }
 
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 5e4ae42..5f402d9 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -97,7 +97,8 @@ SPI_connect(void)
 		newdepth = 16;
 		_SPI_stack = (_SPI_connection *)
 			MemoryContextAlloc(TopTransactionContext,
-							   newdepth * sizeof(_SPI_connection));
+							   newdepth * sizeof(_SPI_connection),
+							   FileAndLineTag());
 		_SPI_stack_depth = newdepth;
 	}
 	else
diff --git a/src/backend/executor/tstoreReceiver.c b/src/backend/executor/tstoreReceiver.c
index c98ff2b..8acdd55 100644
--- a/src/backend/executor/tstoreReceiver.c
+++ b/src/backend/executor/tstoreReceiver.c
@@ -74,9 +74,11 @@ tstoreStartupReceiver(DestReceiver *self, int operation, TupleDesc typeinfo)
 		myState->pub.receiveSlot = tstoreReceiveSlot_detoast;
 		/* Create workspace */
 		myState->outvalues = (Datum *)
-			MemoryContextAlloc(myState->cxt, natts * sizeof(Datum));
+			MemoryContextAlloc(myState->cxt, natts * sizeof(Datum),
+			FileAndLineTag());
 		myState->tofree = (Datum *)
-			MemoryContextAlloc(myState->cxt, natts * sizeof(Datum));
+			MemoryContextAlloc(myState->cxt, natts * sizeof(Datum),
+			FileAndLineTag());
 	}
 	else
 	{
diff --git a/src/backend/libpq/be-fsstubs.c b/src/backend/libpq/be-fsstubs.c
index 6f7e474..de07a27 100644
--- a/src/backend/libpq/be-fsstubs.c
+++ b/src/backend/libpq/be-fsstubs.c
@@ -635,7 +635,8 @@ newLOfd(LargeObjectDesc *lobjCookie)
 		i = 0;
 		newsize = 64;
 		cookies = (LargeObjectDesc **)
-			MemoryContextAllocZero(fscxt, newsize * sizeof(LargeObjectDesc *));
+			MemoryContextAllocZero(fscxt, newsize * sizeof(LargeObjectDesc *),
+								   FileAndLineTag());
 		cookies_size = newsize;
 	}
 	else
diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c
index dce0eaa..bc5fcbb 100644
--- a/src/backend/libpq/be-secure.c
+++ b/src/backend/libpq/be-secure.c
@@ -961,7 +961,8 @@ aloop:
 		{
 			char	   *peer_cn;
 
-			peer_cn = MemoryContextAlloc(TopMemoryContext, len + 1);
+			peer_cn = MemoryContextAlloc(TopMemoryContext, len + 1,
+										 FileAndLineTag());
 			r = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer),
 										  NID_commonName, peer_cn, len + 1);
 			peer_cn[len] = '\0';
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index 2082e3d..731391d 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -153,7 +153,8 @@ void
 pq_init(void)
 {
 	PqSendBufferSize = PQ_SEND_BUFFER_SIZE;
-	PqSendBuffer = MemoryContextAlloc(TopMemoryContext, PqSendBufferSize);
+	PqSendBuffer = MemoryContextAlloc(TopMemoryContext, PqSendBufferSize,
+									  FileAndLineTag());
 	PqSendPointer = PqSendStart = PqRecvPointer = PqRecvLength = 0;
 	PqCommBusy = false;
 	DoingCopyOut = false;
diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c
index 4c904e0..68f65fc 100644
--- a/src/backend/nodes/bitmapset.c
+++ b/src/backend/nodes/bitmapset.c
@@ -107,7 +107,7 @@ static const uint8 number_of_ones[256] = {
  * bms_copy - make a palloc'd copy of a bitmapset
  */
 Bitmapset *
-bms_copy(const Bitmapset *a)
+bms_copy_really(const Bitmapset *a, const char *tag)
 {
 	Bitmapset  *result;
 	size_t		size;
@@ -115,7 +115,7 @@ bms_copy(const Bitmapset *a)
 	if (a == NULL)
 		return NULL;
 	size = BITMAPSET_SIZE(a->nwords);
-	result = (Bitmapset *) palloc(size);
+	result = (Bitmapset *) MemoryContextAlloc(CurrentMemoryContext, size, tag);
 	memcpy(result, a, size);
 	return result;
 }
@@ -175,7 +175,7 @@ bms_equal(const Bitmapset *a, const Bitmapset *b)
  * bms_make_singleton - build a bitmapset containing a single member
  */
 Bitmapset *
-bms_make_singleton(int x)
+bms_make_singleton_really(int x, const char *tag)
 {
 	Bitmapset  *result;
 	int			wordnum,
@@ -185,7 +185,9 @@ bms_make_singleton(int x)
 		elog(ERROR, "negative bitmapset member not allowed");
 	wordnum = WORDNUM(x);
 	bitnum = BITNUM(x);
-	result = (Bitmapset *) palloc0(BITMAPSET_SIZE(wordnum + 1));
+	result = (Bitmapset *) MemoryContextAllocZero(CurrentMemoryContext,
+												  BITMAPSET_SIZE(wordnum + 1),
+												  tag);
 	result->nwords = wordnum + 1;
 	result->words[wordnum] = ((bitmapword) 1 << bitnum);
 	return result;
@@ -621,7 +623,7 @@ bms_is_empty(const Bitmapset *a)
  * Input set is modified or recycled!
  */
 Bitmapset *
-bms_add_member(Bitmapset *a, int x)
+bms_add_member_really(Bitmapset *a, int x, const char *tag)
 {
 	int			wordnum,
 				bitnum;
@@ -629,7 +631,7 @@ bms_add_member(Bitmapset *a, int x)
 	if (x < 0)
 		elog(ERROR, "negative bitmapset member not allowed");
 	if (a == NULL)
-		return bms_make_singleton(x);
+		return bms_make_singleton_really(x, tag);
 	wordnum = WORDNUM(x);
 	bitnum = BITNUM(x);
 	if (wordnum >= a->nwords)
@@ -679,7 +681,7 @@ bms_del_member(Bitmapset *a, int x)
  * bms_add_members - like bms_union, but left input is recycled
  */
 Bitmapset *
-bms_add_members(Bitmapset *a, const Bitmapset *b)
+bms_add_members_really(Bitmapset *a, const Bitmapset *b, const char *tag)
 {
 	Bitmapset  *result;
 	const Bitmapset *other;
@@ -688,13 +690,13 @@ bms_add_members(Bitmapset *a, const Bitmapset *b)
 
 	/* Handle cases where either input is NULL */
 	if (a == NULL)
-		return bms_copy(b);
+		return bms_copy_really(b, tag);
 	if (b == NULL)
 		return a;
 	/* Identify shorter and longer input; copy the longer one if needed */
 	if (a->nwords < b->nwords)
 	{
-		result = bms_copy(b);
+		result = bms_copy_really(b, tag);
 		other = a;
 	}
 	else
diff --git a/src/backend/nodes/list.c b/src/backend/nodes/list.c
index 209b722..3c9f94d 100644
--- a/src/backend/nodes/list.c
+++ b/src/backend/nodes/list.c
@@ -60,16 +60,18 @@ check_list_invariants(const List *list)
  * the caller should be sure to fill in that cell's data.
  */
 static List *
-new_list(NodeTag type)
+new_list(NodeTag type, const char *tag)
 {
 	List	   *new_list;
 	ListCell   *new_head;
 
-	new_head = (ListCell *) palloc(sizeof(*new_head));
+	new_head = (ListCell *) MemoryContextAlloc(CurrentMemoryContext,
+											   sizeof(*new_head), tag);
 	new_head->next = NULL;
 	/* new_head->data is left undefined! */
 
-	new_list = (List *) palloc(sizeof(*new_list));
+	new_list = (List *) MemoryContextAlloc(CurrentMemoryContext,
+										   sizeof(*new_list), tag);
 	new_list->type = type;
 	new_list->length = 1;
 	new_list->head = new_head;
@@ -105,11 +107,12 @@ new_head_cell(List *list)
  * sure to fill it in
  */
 static void
-new_tail_cell(List *list)
+new_tail_cell(List *list, const char *tag)
 {
 	ListCell   *new_tail;
 
-	new_tail = (ListCell *) palloc(sizeof(*new_tail));
+	new_tail = (ListCell *) MemoryContextAlloc(CurrentMemoryContext,
+											   sizeof(*new_tail), tag);
 	new_tail->next = NULL;
 
 	list->tail->next = new_tail;
@@ -125,14 +128,14 @@ new_tail_cell(List *list)
  * first argument.
  */
 List *
-lappend(List *list, void *datum)
+lappend_really(List *list, void *datum, const char *tag)
 {
 	Assert(IsPointerList(list));
 
 	if (list == NIL)
-		list = new_list(T_List);
+		list = new_list(T_List, tag);
 	else
-		new_tail_cell(list);
+		new_tail_cell(list, tag);
 
 	lfirst(list->tail) = datum;
 	check_list_invariants(list);
@@ -143,14 +146,14 @@ lappend(List *list, void *datum)
  * Append an integer to the specified list. See lappend()
  */
 List *
-lappend_int(List *list, int datum)
+lappend_int_really(List *list, int datum, const char *tag)
 {
 	Assert(IsIntegerList(list));
 
 	if (list == NIL)
-		list = new_list(T_IntList);
+		list = new_list(T_IntList, tag);
 	else
-		new_tail_cell(list);
+		new_tail_cell(list, tag);
 
 	lfirst_int(list->tail) = datum;
 	check_list_invariants(list);
@@ -161,14 +164,14 @@ lappend_int(List *list, int datum)
  * Append an OID to the specified list. See lappend()
  */
 List *
-lappend_oid(List *list, Oid datum)
+lappend_oid_really(List *list, Oid datum, const char *tag)
 {
 	Assert(IsOidList(list));
 
 	if (list == NIL)
-		list = new_list(T_OidList);
+		list = new_list(T_OidList, tag);
 	else
-		new_tail_cell(list);
+		new_tail_cell(list, tag);
 
 	lfirst_oid(list->tail) = datum;
 	check_list_invariants(list);
@@ -256,12 +259,12 @@ lappend_cell_oid(List *list, ListCell *prev, Oid datum)
  * the case.
  */
 List *
-lcons(void *datum, List *list)
+lcons_really(void *datum, List *list, const char *tag)
 {
 	Assert(IsPointerList(list));
 
 	if (list == NIL)
-		list = new_list(T_List);
+		list = new_list(T_List, tag);
 	else
 		new_head_cell(list);
 
@@ -274,12 +277,12 @@ lcons(void *datum, List *list)
  * Prepend an integer to the list. See lcons()
  */
 List *
-lcons_int(int datum, List *list)
+lcons_int_really(int datum, List *list, const char *tag)
 {
 	Assert(IsIntegerList(list));
 
 	if (list == NIL)
-		list = new_list(T_IntList);
+		list = new_list(T_IntList, tag);
 	else
 		new_head_cell(list);
 
@@ -292,12 +295,12 @@ lcons_int(int datum, List *list)
  * Prepend an OID to the list. See lcons()
  */
 List *
-lcons_oid(Oid datum, List *list)
+lcons_oid_really(Oid datum, List *list, const char *tag)
 {
 	Assert(IsOidList(list));
 
 	if (list == NIL)
-		list = new_list(T_OidList);
+		list = new_list(T_OidList, tag);
 	else
 		new_head_cell(list);
 
@@ -933,12 +936,12 @@ list_difference_oid(const List *list1, const List *list2)
  * via equal().
  */
 List *
-list_append_unique(List *list, void *datum)
+list_append_unique_really(List *list, void *datum, const char *tag)
 {
 	if (list_member(list, datum))
 		return list;
 	else
-		return lappend(list, datum);
+		return lappend_really(list, datum, tag);
 }
 
 /*
@@ -946,36 +949,36 @@ list_append_unique(List *list, void *datum)
  * simple pointer equality.
  */
 List *
-list_append_unique_ptr(List *list, void *datum)
+list_append_unique_ptr_really(List *list, void *datum, const char *tag)
 {
 	if (list_member_ptr(list, datum))
 		return list;
 	else
-		return lappend(list, datum);
+		return lappend_really(list, datum, tag);
 }
 
 /*
  * This variant of list_append_unique() operates upon lists of integers.
  */
 List *
-list_append_unique_int(List *list, int datum)
+list_append_unique_int_really(List *list, int datum, const char *tag)
 {
 	if (list_member_int(list, datum))
 		return list;
 	else
-		return lappend_int(list, datum);
+		return lappend_int_really(list, datum, tag);
 }
 
 /*
  * This variant of list_append_unique() operates upon lists of OIDs.
  */
 List *
-list_append_unique_oid(List *list, Oid datum)
+list_append_unique_oid_really(List *list, Oid datum, const char *tag)
 {
 	if (list_member_oid(list, datum))
 		return list;
 	else
-		return lappend_oid(list, datum);
+		return lappend_oid_really(list, datum, tag);
 }
 
 /*
@@ -1131,7 +1134,7 @@ list_free_deep(List *list)
  * Return a shallow copy of the specified list.
  */
 List *
-list_copy(const List *oldlist)
+list_copy_really(const List *oldlist, const char *tag)
 {
 	List	   *newlist;
 	ListCell   *newlist_prev;
@@ -1140,7 +1143,7 @@ list_copy(const List *oldlist)
 	if (oldlist == NIL)
 		return NIL;
 
-	newlist = new_list(oldlist->type);
+	newlist = new_list(oldlist->type, tag);
 	newlist->length = oldlist->length;
 
 	/*
@@ -1155,7 +1158,9 @@ list_copy(const List *oldlist)
 	{
 		ListCell   *newlist_cur;
 
-		newlist_cur = (ListCell *) palloc(sizeof(*newlist_cur));
+		newlist_cur = (ListCell *) MemoryContextAlloc(CurrentMemoryContext,
+													  sizeof(*newlist_cur),
+													  tag);
 		newlist_cur->data = oldlist_cur->data;
 		newlist_prev->next = newlist_cur;
 
@@ -1174,7 +1179,7 @@ list_copy(const List *oldlist)
  * Return a shallow copy of the specified list, without the first N elements.
  */
 List *
-list_copy_tail(const List *oldlist, int nskip)
+list_copy_tail_really(const List *oldlist, int nskip, const char *tag)
 {
 	List	   *newlist;
 	ListCell   *newlist_prev;
@@ -1186,7 +1191,7 @@ list_copy_tail(const List *oldlist, int nskip)
 	if (oldlist == NIL || nskip >= oldlist->length)
 		return NIL;
 
-	newlist = new_list(oldlist->type);
+	newlist = new_list(oldlist->type, tag);
 	newlist->length = oldlist->length - nskip;
 
 	/*
@@ -1208,7 +1213,9 @@ list_copy_tail(const List *oldlist, int nskip)
 	{
 		ListCell   *newlist_cur;
 
-		newlist_cur = (ListCell *) palloc(sizeof(*newlist_cur));
+		newlist_cur = (ListCell *) MemoryContextAlloc(CurrentMemoryContext,
+													  sizeof(*newlist_cur),
+													  tag);
 		newlist_cur->data = oldlist_cur->data;
 		newlist_prev->next = newlist_cur;
 
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index bb5cdae..2da407c 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -63,14 +63,15 @@ makeSimpleA_Expr(A_Expr_Kind kind, char *name,
  *	  creates a Var node
  */
 Var *
-makeVar(Index varno,
+makeVar_really(Index varno,
 		AttrNumber varattno,
 		Oid vartype,
 		int32 vartypmod,
 		Oid varcollid,
-		Index varlevelsup)
+		Index varlevelsup,
+		const char *tag)
 {
-	Var		   *var = makeNode(Var);
+	Var		   *var = makeNodeWithTag(Var, tag);
 
 	var->varno = varno;
 	var->varattno = varattno;
@@ -100,15 +101,16 @@ makeVar(Index varno,
  *		TargetEntry
  */
 Var *
-makeVarFromTargetEntry(Index varno,
-					   TargetEntry *tle)
+makeVarFromTargetEntry_really(Index varno,
+					   TargetEntry *tle,
+					   const char *tag)
 {
-	return makeVar(varno,
+	return makeVar_really(varno,
 				   tle->resno,
 				   exprType((Node *) tle->expr),
 				   exprTypmod((Node *) tle->expr),
 				   exprCollation((Node *) tle->expr),
-				   0);
+				   0, tag);
 }
 
 /*
@@ -209,13 +211,15 @@ makeWholeRowVar(RangeTblEntry *rte,
  *	  creates a TargetEntry node
  */
 TargetEntry *
-makeTargetEntry(Expr *expr,
+makeTargetEntry_really(Expr *expr,
 				AttrNumber resno,
 				char *resname,
-				bool resjunk)
+				bool resjunk,
+				const char *tag)
 {
-	TargetEntry *tle = makeNode(TargetEntry);
+	TargetEntry *tle;
 
+	tle = makeNodeWithTag(TargetEntry, tag);
 	tle->expr = expr;
 	tle->resno = resno;
 	tle->resname = resname;
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 17dae0d..79d2e25 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -598,11 +598,13 @@ tbm_begin_iterate(TIDBitmap *tbm)
 		if (!tbm->spages && tbm->npages > 0)
 			tbm->spages = (PagetableEntry **)
 				MemoryContextAlloc(tbm->mcxt,
-								   tbm->npages * sizeof(PagetableEntry *));
+								   tbm->npages * sizeof(PagetableEntry *),
+								   FileAndLineTag());
 		if (!tbm->schunks && tbm->nchunks > 0)
 			tbm->schunks = (PagetableEntry **)
 				MemoryContextAlloc(tbm->mcxt,
-								   tbm->nchunks * sizeof(PagetableEntry *));
+								   tbm->nchunks * sizeof(PagetableEntry *),
+								   FileAndLineTag());
 
 		hash_seq_init(&status, tbm->pagetable);
 		npages = nchunks = 0;
diff --git a/src/backend/nodes/value.c b/src/backend/nodes/value.c
index 2788e0e..59bce3f 100644
--- a/src/backend/nodes/value.c
+++ b/src/backend/nodes/value.c
@@ -50,9 +50,9 @@ makeFloat(char *numericStr)
  * Caller is responsible for passing a palloc'd string.
  */
 Value *
-makeString(char *str)
+makeString_really(char *str, const char *tag)
 {
-	Value	   *v = makeNode(Value);
+	Value	   *v = makeNodeWithTag(Value, tag);
 
 	v->type = T_String;
 	v->val.str = str;
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index c34b9b8..c513cf3 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -428,11 +428,10 @@ build_relation_tlist(RelOptInfo *rel)
 	{
 		/* Do we really need to copy here?	Not sure */
 		Node	   *node = (Node *) copyObject(lfirst(v));
+		TargetEntry *tle;
 
-		tlist = lappend(tlist, makeTargetEntry((Expr *) node,
-											   resno,
-											   NULL,
-											   false));
+		tle = makeTargetEntry((Expr *) node, resno, NULL, false);
+		tlist = lappend(tlist, tle);
 		resno++;
 	}
 	return tlist;
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index aaf288a..bfab467 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -850,6 +850,7 @@ build_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
 			for (attrno = 1; attrno <= numattrs; attrno++)
 			{
 				Form_pg_attribute att_tup = relation->rd_att->attrs[attrno - 1];
+				TargetEntry *tle;
 
 				if (att_tup->attisdropped)
 				{
@@ -865,11 +866,8 @@ build_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
 							  att_tup->attcollation,
 							  0);
 
-				tlist = lappend(tlist,
-								makeTargetEntry((Expr *) var,
-												attrno,
-												NULL,
-												false));
+				tle = makeTargetEntry((Expr *) var, attrno, NULL, false);
+				tlist = lappend(tlist, tle);
 			}
 
 			heap_close(relation, NoLock);
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 2a26b0a..475cc1c 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -746,7 +746,8 @@ buildRelationAliases(TupleDesc tupdesc, Alias *alias, Alias *eref)
 		}
 		else
 		{
-			attrname = makeString(pstrdup(NameStr(attr->attname)));
+			char *x = pstrdup(NameStr(attr->attname));
+			attrname = makeString(x);
 			/* we're done with the alias if any */
 		}
 
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 424cfca..cd4b3b2 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -1629,7 +1629,8 @@ get_tabstat_entry(Oid rel_id, bool isshared)
 	 * We ran out of tabstat slots, so allocate more.  Be sure they're zeroed.
 	 */
 	tsa = (TabStatusArray *) MemoryContextAllocZero(TopMemoryContext,
-													sizeof(TabStatusArray));
+													sizeof(TabStatusArray),
+													FileAndLineTag());
 	if (prev_tsa)
 		prev_tsa->tsa_next = tsa;
 	else
@@ -1683,7 +1684,7 @@ get_tabstat_stack_level(int nest_level)
 	{
 		xact_state = (PgStat_SubXactStatus *)
 			MemoryContextAlloc(TopTransactionContext,
-							   sizeof(PgStat_SubXactStatus));
+							   sizeof(PgStat_SubXactStatus), FileAndLineTag());
 		xact_state->nest_level = nest_level;
 		xact_state->prev = pgStatXactStack;
 		xact_state->first = NULL;
@@ -1710,7 +1711,8 @@ add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level)
 	/* Now make a per-table stack entry */
 	trans = (PgStat_TableXactStatus *)
 		MemoryContextAllocZero(TopTransactionContext,
-							   sizeof(PgStat_TableXactStatus));
+							   sizeof(PgStat_TableXactStatus),
+							   FileAndLineTag());
 	trans->nest_level = nest_level;
 	trans->upper = pgstat_info->trans;
 	trans->parent = pgstat_info;
@@ -2696,13 +2698,15 @@ pgstat_read_current_status(void)
 
 	localtable = (PgBackendStatus *)
 		MemoryContextAlloc(pgStatLocalContext,
-						   sizeof(PgBackendStatus) * MaxBackends);
+						   sizeof(PgBackendStatus) * MaxBackends,
+						   FileAndLineTag());
 	localappname = (char *)
 		MemoryContextAlloc(pgStatLocalContext,
-						   NAMEDATALEN * MaxBackends);
+						   NAMEDATALEN * MaxBackends, FileAndLineTag());
 	localactivity = (char *)
 		MemoryContextAlloc(pgStatLocalContext,
-						   pgstat_track_activity_query_size * MaxBackends);
+						   pgstat_track_activity_query_size * MaxBackends,
+						   FileAndLineTag());
 	localNumBackends = 0;
 
 	beentry = BackendStatusArray;
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index dd7dd55..ffd60d7 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -3564,7 +3564,8 @@ BackendRun(Port *port)
 	maxac += (strlen(ExtraOptions) + 1) / 2;
 
 	av = (char **) MemoryContextAlloc(TopMemoryContext,
-									  maxac * sizeof(char *));
+									  maxac * sizeof(char *),
+									  FileAndLineTag());
 	ac = 0;
 
 	av[ac++] = "postgres";
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 63c14f7..939e39a 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -434,7 +434,8 @@ GetLocalBufferStorage(void)
 		num_bufs = Min(num_bufs, MaxAllocSize / BLCKSZ);
 
 		cur_block = (char *) MemoryContextAlloc(LocalBufferContext,
-												num_bufs * BLCKSZ);
+												num_bufs * BLCKSZ,
+												FileAndLineTag());
 		next_buf_in_block = 0;
 		num_bufs_in_block = num_bufs;
 	}
diff --git a/src/backend/storage/ipc/ipc.c b/src/backend/storage/ipc/ipc.c
index 067b24a..0a7159c 100644
--- a/src/backend/storage/ipc/ipc.c
+++ b/src/backend/storage/ipc/ipc.c
@@ -29,6 +29,7 @@
 #endif
 #include "storage/ipc.h"
 #include "tcop/tcopprot.h"
+#include "utils/memutils.h"
 
 
 /*
@@ -134,6 +135,8 @@ proc_exit(int code)
 
 	elog(DEBUG3, "exit(%d)", code);
 
+	dump_allocations();
+
 	exit(code);
 }
 
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index 3adfb15..95487be 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -241,7 +241,8 @@ inv_open(Oid lobjId, int flags, MemoryContext mcxt)
 	LargeObjectDesc *retval;
 
 	retval = (LargeObjectDesc *) MemoryContextAlloc(mcxt,
-													sizeof(LargeObjectDesc));
+													sizeof(LargeObjectDesc),
+													FileAndLineTag());
 
 	retval->id = lobjId;
 	retval->subid = GetCurrentSubTransactionId();
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 50b95ac..ab33268 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -652,7 +652,8 @@ LockAcquireExtended(const LOCKTAG *locktag,
 		locallock->lockOwners = NULL;
 		locallock->lockOwners = (LOCALLOCKOWNER *)
 			MemoryContextAlloc(TopMemoryContext,
-						  locallock->maxLockOwners * sizeof(LOCALLOCKOWNER));
+						  locallock->maxLockOwners * sizeof(LOCALLOCKOWNER),
+						  FileAndLineTag());
 	}
 	else
 	{
@@ -2468,7 +2469,8 @@ GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode)
 		if (vxids == NULL)
 			vxids = (VirtualTransactionId *)
 				MemoryContextAlloc(TopMemoryContext,
-						   sizeof(VirtualTransactionId) * (MaxBackends + 1));
+						   sizeof(VirtualTransactionId) * (MaxBackends + 1),
+						   FileAndLineTag());
 	}
 	else
 		vxids = (VirtualTransactionId *)
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index eeb20fd..52e58ca 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -1510,7 +1510,8 @@ ForgetDatabaseFsyncRequests(Oid dbid)
 static MdfdVec *
 _fdvec_alloc(void)
 {
-	return (MdfdVec *) MemoryContextAlloc(MdCxt, sizeof(MdfdVec));
+	return (MdfdVec *) MemoryContextAlloc(MdCxt, sizeof(MdfdVec),
+										  FileAndLineTag());
 }
 
 /*
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index d0db7ad..1e9169e 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -652,7 +652,7 @@ PortalSetResultFormat(Portal portal, int nFormats, int16 *formats)
 	natts = portal->tupDesc->natts;
 	portal->formats = (int16 *)
 		MemoryContextAlloc(PortalGetHeapMemory(portal),
-						   natts * sizeof(int16));
+						   natts * sizeof(int16), FileAndLineTag());
 	if (nFormats > 1)
 	{
 		/* format specified for each column */
diff --git a/src/backend/tsearch/spell.c b/src/backend/tsearch/spell.c
index 2fe40ed..ac9ce52 100644
--- a/src/backend/tsearch/spell.c
+++ b/src/backend/tsearch/spell.c
@@ -27,8 +27,8 @@
  * with the dictionary cache entry.  We keep the short-lived stuff
  * in the Conf->buildCxt context.
  */
-#define tmpalloc(sz)  MemoryContextAlloc(Conf->buildCxt, (sz))
-#define tmpalloc0(sz)  MemoryContextAllocZero(Conf->buildCxt, (sz))
+#define tmpalloc(sz)  MemoryContextAlloc(Conf->buildCxt, (sz), FileAndLineTag())
+#define tmpalloc0(sz)  MemoryContextAllocZero(Conf->buildCxt, (sz), FileAndLineTag())
 
 /*
  * Prepare for constructing an ISpell dictionary.
diff --git a/src/backend/utils/adt/array_typanalyze.c b/src/backend/utils/adt/array_typanalyze.c
index fa79d9f..5988dcf 100644
--- a/src/backend/utils/adt/array_typanalyze.c
+++ b/src/backend/utils/adt/array_typanalyze.c
@@ -608,7 +608,8 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
 			 */
 			hist = (float4 *)
 				MemoryContextAlloc(stats->anl_context,
-								   sizeof(float4) * (num_hist + 1));
+								   sizeof(float4) * (num_hist + 1),
+								   FileAndLineTag());
 			hist[num_hist] = (double) element_no / (double) nonnull_cnt;
 
 			/*----------
diff --git a/src/backend/utils/adt/array_userfuncs.c b/src/backend/utils/adt/array_userfuncs.c
index a6ba0cf..b76a031 100644
--- a/src/backend/utils/adt/array_userfuncs.c
+++ b/src/backend/utils/adt/array_userfuncs.c
@@ -128,7 +128,8 @@ array_push(PG_FUNCTION_ARGS)
 	if (my_extra == NULL)
 	{
 		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-													  sizeof(ArrayMetaState));
+													  sizeof(ArrayMetaState),
+													  FileAndLineTag());
 		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
 		my_extra->element_type = ~element_type;
 	}
@@ -447,7 +448,8 @@ create_singleton_array(FunctionCallInfo fcinfo,
 	if (my_extra == NULL)
 	{
 		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-													  sizeof(ArrayMetaState));
+													  sizeof(ArrayMetaState),
+													  FileAndLineTag());
 		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
 		my_extra->element_type = ~element_type;
 	}
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 5582a06..764ea34 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -170,7 +170,8 @@ array_in(PG_FUNCTION_ARGS)
 	if (my_extra == NULL)
 	{
 		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-													  sizeof(ArrayMetaState));
+													  sizeof(ArrayMetaState),
+													  FileAndLineTag());
 		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
 		my_extra->element_type = ~element_type;
 	}
@@ -990,7 +991,8 @@ array_out(PG_FUNCTION_ARGS)
 	if (my_extra == NULL)
 	{
 		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-													  sizeof(ArrayMetaState));
+													  sizeof(ArrayMetaState),
+													  FileAndLineTag());
 		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
 		my_extra->element_type = ~element_type;
 	}
@@ -1288,7 +1290,8 @@ array_recv(PG_FUNCTION_ARGS)
 	if (my_extra == NULL)
 	{
 		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-													  sizeof(ArrayMetaState));
+													  sizeof(ArrayMetaState),
+													  FileAndLineTag());
 		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
 		my_extra->element_type = ~element_type;
 	}
@@ -1510,7 +1513,8 @@ array_send(PG_FUNCTION_ARGS)
 	if (my_extra == NULL)
 	{
 		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-													  sizeof(ArrayMetaState));
+													  sizeof(ArrayMetaState),
+													  FileAndLineTag());
 		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
 		my_extra->element_type = ~element_type;
 	}
@@ -4990,7 +4994,8 @@ array_fill_internal(ArrayType *dims, ArrayType *lbs,
 	if (my_extra == NULL)
 	{
 		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-													  sizeof(ArrayMetaState));
+													  sizeof(ArrayMetaState),
+													  FileAndLineTag());
 		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
 		my_extra->element_type = InvalidOid;
 	}
diff --git a/src/backend/utils/adt/domains.c b/src/backend/utils/adt/domains.c
index 591d992..fd8a44e 100644
--- a/src/backend/utils/adt/domains.c
+++ b/src/backend/utils/adt/domains.c
@@ -214,7 +214,8 @@ domain_in(PG_FUNCTION_ARGS)
 	if (my_extra == NULL)
 	{
 		my_extra = (DomainIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-													   sizeof(DomainIOData));
+													   sizeof(DomainIOData),
+													   FileAndLineTag());
 		domain_state_setup(my_extra, domainType, false,
 						   fcinfo->flinfo->fn_mcxt);
 		fcinfo->flinfo->fn_extra = (void *) my_extra;
@@ -274,7 +275,8 @@ domain_recv(PG_FUNCTION_ARGS)
 	if (my_extra == NULL)
 	{
 		my_extra = (DomainIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-													   sizeof(DomainIOData));
+													   sizeof(DomainIOData),
+													   FileAndLineTag());
 		domain_state_setup(my_extra, domainType, true,
 						   fcinfo->flinfo->fn_mcxt);
 		fcinfo->flinfo->fn_extra = (void *) my_extra;
@@ -325,7 +327,8 @@ domain_check(Datum value, bool isnull, Oid domainType, void **extra, MemoryConte
 	if (my_extra == NULL)
 	{
 		my_extra = (DomainIOData *) MemoryContextAlloc(mcxt,
-													   sizeof(DomainIOData));
+													   sizeof(DomainIOData),
+													   FileAndLineTag());
 		domain_state_setup(my_extra, domainType, true, mcxt);
 		if (extra)
 			*extra = (void *) my_extra;
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 83d0c22..4000a85 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -476,7 +476,7 @@ pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
 		funcctx = SRF_FIRSTCALL_INIT();
 
 		fctx = MemoryContextAlloc(funcctx->multi_call_memory_ctx,
-								  2 * sizeof(int));
+								  2 * sizeof(int), FileAndLineTag());
 		funcctx->user_fctx = fctx;
 
 		fctx[0] = 0;
diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c
index 0994fa7..def2bad 100644
--- a/src/backend/utils/adt/rangetypes.c
+++ b/src/backend/utils/adt/rangetypes.c
@@ -305,7 +305,8 @@ get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
 		char	typdelim;
 
 		cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-												   sizeof(RangeIOData));
+												   sizeof(RangeIOData),
+												   FileAndLineTag());
 		cache->typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
 		if (cache->typcache->rngelemtype == NULL)
 			elog(ERROR, "type %u is not a range type", rngtypid);
diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index ba7fde4..54e514c 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -117,7 +117,8 @@ record_in(PG_FUNCTION_ARGS)
 		fcinfo->flinfo->fn_extra =
 			MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
 							   sizeof(RecordIOData) - sizeof(ColumnIOData)
-							   + ncolumns * sizeof(ColumnIOData));
+							   + ncolumns * sizeof(ColumnIOData),
+							  FileAndLineTag());
 		my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
 		my_extra->record_type = InvalidOid;
 		my_extra->record_typmod = 0;
@@ -331,7 +332,8 @@ record_out(PG_FUNCTION_ARGS)
 		fcinfo->flinfo->fn_extra =
 			MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
 							   sizeof(RecordIOData) - sizeof(ColumnIOData)
-							   + ncolumns * sizeof(ColumnIOData));
+							   + ncolumns * sizeof(ColumnIOData),
+							  FileAndLineTag());
 		my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
 		my_extra->record_type = InvalidOid;
 		my_extra->record_typmod = 0;
@@ -486,7 +488,8 @@ record_recv(PG_FUNCTION_ARGS)
 		fcinfo->flinfo->fn_extra =
 			MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
 							   sizeof(RecordIOData) - sizeof(ColumnIOData)
-							   + ncolumns * sizeof(ColumnIOData));
+							   + ncolumns * sizeof(ColumnIOData),
+							  FileAndLineTag());
 		my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
 		my_extra->record_type = InvalidOid;
 		my_extra->record_typmod = 0;
@@ -674,7 +677,8 @@ record_send(PG_FUNCTION_ARGS)
 		fcinfo->flinfo->fn_extra =
 			MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
 							   sizeof(RecordIOData) - sizeof(ColumnIOData)
-							   + ncolumns * sizeof(ColumnIOData));
+							   + ncolumns * sizeof(ColumnIOData),
+							   FileAndLineTag());
 		my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
 		my_extra->record_type = InvalidOid;
 		my_extra->record_typmod = 0;
@@ -829,7 +833,8 @@ record_cmp(FunctionCallInfo fcinfo)
 		fcinfo->flinfo->fn_extra =
 			MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
 						sizeof(RecordCompareData) - sizeof(ColumnCompareData)
-							   + ncols * sizeof(ColumnCompareData));
+							   + ncols * sizeof(ColumnCompareData),
+						FileAndLineTag());
 		my_extra = (RecordCompareData *) fcinfo->flinfo->fn_extra;
 		my_extra->ncolumns = ncols;
 		my_extra->record1_type = InvalidOid;
@@ -1064,7 +1069,8 @@ record_eq(PG_FUNCTION_ARGS)
 		fcinfo->flinfo->fn_extra =
 			MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
 						sizeof(RecordCompareData) - sizeof(ColumnCompareData)
-							   + ncols * sizeof(ColumnCompareData));
+							   + ncols * sizeof(ColumnCompareData),
+						FileAndLineTag());
 		my_extra = (RecordCompareData *) fcinfo->flinfo->fn_extra;
 		my_extra->ncolumns = ncols;
 		my_extra->record1_type = InvalidOid;
diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c
index bab6534..c63284b 100644
--- a/src/backend/utils/adt/tsvector_op.c
+++ b/src/backend/utils/adt/tsvector_op.c
@@ -918,7 +918,8 @@ insertStatEntry(MemoryContext persistentContext, TSVectorStat *stat, TSVector tx
 
 	if (node == NULL)
 	{
-		node = MemoryContextAlloc(persistentContext, STATENTRYHDRSZ + we->len);
+		node = MemoryContextAlloc(persistentContext, STATENTRYHDRSZ + we->len,
+								  FileAndLineTag());
 		node->left = node->right = NULL;
 		node->ndoc = 1;
 		node->nentry = n;
@@ -987,7 +988,8 @@ ts_accum(MemoryContext persistentContext, TSVectorStat *stat, Datum data)
 
 	if (stat == NULL)
 	{							/* Init in first */
-		stat = MemoryContextAllocZero(persistentContext, sizeof(TSVectorStat));
+		stat = MemoryContextAllocZero(persistentContext, sizeof(TSVectorStat),
+									  FileAndLineTag());
 		stat->maxdepth = 1;
 	}
 
@@ -1172,7 +1174,8 @@ ts_stat_sql(MemoryContext persistentContext, text *txt, text *ws)
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("ts_stat query must return one tsvector column")));
 
-	stat = MemoryContextAllocZero(persistentContext, sizeof(TSVectorStat));
+	stat = MemoryContextAllocZero(persistentContext, sizeof(TSVectorStat),
+								  FileAndLineTag());
 	stat->maxdepth = 1;
 
 	if (ws)
diff --git a/src/backend/utils/adt/txid.c b/src/backend/utils/adt/txid.c
index 08a8c89..699ed3d 100644
--- a/src/backend/utils/adt/txid.c
+++ b/src/backend/utils/adt/txid.c
@@ -571,7 +571,8 @@ txid_snapshot_xip(PG_FUNCTION_ARGS)
 		fctx = SRF_FIRSTCALL_INIT();
 
 		/* make a copy of user snapshot */
-		snap = MemoryContextAlloc(fctx->multi_call_memory_ctx, VARSIZE(arg));
+		snap = MemoryContextAlloc(fctx->multi_call_memory_ctx, VARSIZE(arg),
+								  FileAndLineTag());
 		memcpy(snap, arg, VARSIZE(arg));
 
 		fctx->user_fctx = snap;
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index a5592d5..77fd250 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -3381,7 +3381,8 @@ array_to_text_internal(FunctionCallInfo fcinfo, ArrayType *v,
 	if (my_extra == NULL)
 	{
 		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-													  sizeof(ArrayMetaState));
+													  sizeof(ArrayMetaState),
+													  FileAndLineTag());
 		my_extra = (ArrayMetaState *) fcinfo->flinfo->fn_extra;
 		my_extra->element_type = ~element_type;
 	}
@@ -3578,7 +3579,8 @@ pg_column_size(PG_FUNCTION_ARGS)
 			elog(ERROR, "cache lookup failed for type %u", argtypeid);
 
 		fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
-													  sizeof(int));
+													  sizeof(int),
+													  FileAndLineTag());
 		*((int *) fcinfo->flinfo->fn_extra) = typlen;
 	}
 	else
diff --git a/src/backend/utils/cache/attoptcache.c b/src/backend/utils/cache/attoptcache.c
index e01ae21..0cdaf1f 100644
--- a/src/backend/utils/cache/attoptcache.c
+++ b/src/backend/utils/cache/attoptcache.c
@@ -153,7 +153,8 @@ get_attribute_options(Oid attrelid, int attnum)
 				bytea	   *bytea_opts = attribute_reloptions(datum, false);
 
 				opts = MemoryContextAlloc(CacheMemoryContext,
-										  VARSIZE(bytea_opts));
+										  VARSIZE(bytea_opts),
+										  FileAndLineTag());
 				memcpy(opts, bytea_opts, VARSIZE(bytea_opts));
 			}
 			ReleaseSysCache(tp);
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index d5fe85a..fd616d0 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -222,7 +222,8 @@ AddInvalidationMessage(InvalidationChunk **listHdr,
 		chunk = (InvalidationChunk *)
 			MemoryContextAlloc(CurTransactionContext,
 							   sizeof(InvalidationChunk) +
-					(FIRSTCHUNKSIZE - 1) *sizeof(SharedInvalidationMessage));
+					(FIRSTCHUNKSIZE - 1) *sizeof(SharedInvalidationMessage),
+					FileAndLineTag());
 		chunk->nitems = 0;
 		chunk->maxitems = FIRSTCHUNKSIZE;
 		chunk->next = *listHdr;
@@ -236,7 +237,8 @@ AddInvalidationMessage(InvalidationChunk **listHdr,
 		chunk = (InvalidationChunk *)
 			MemoryContextAlloc(CurTransactionContext,
 							   sizeof(InvalidationChunk) +
-						 (chunksize - 1) *sizeof(SharedInvalidationMessage));
+						 (chunksize - 1) *sizeof(SharedInvalidationMessage),
+						 FileAndLineTag());
 		chunk->nitems = 0;
 		chunk->maxitems = chunksize;
 		chunk->next = *listHdr;
@@ -629,7 +631,8 @@ AtStart_Inval(void)
 	Assert(transInvalInfo == NULL);
 	transInvalInfo = (TransInvalidationInfo *)
 		MemoryContextAllocZero(TopTransactionContext,
-							   sizeof(TransInvalidationInfo));
+							   sizeof(TransInvalidationInfo),
+							   FileAndLineTag());
 	transInvalInfo->my_level = GetCurrentTransactionNestLevel();
 	SharedInvalidMessagesArray = NULL;
 	numSharedInvalidMessagesArray = 0;
@@ -665,7 +668,8 @@ AtSubStart_Inval(void)
 	Assert(transInvalInfo != NULL);
 	myInfo = (TransInvalidationInfo *)
 		MemoryContextAllocZero(TopTransactionContext,
-							   sizeof(TransInvalidationInfo));
+							   sizeof(TransInvalidationInfo),
+							   FileAndLineTag());
 	myInfo->parent = transInvalInfo;
 	myInfo->my_level = GetCurrentTransactionNestLevel();
 	transInvalInfo = myInfo;
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 7f0e20e..f33b07e 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -399,7 +399,8 @@ RelationParseRelOptions(Relation relation, HeapTuple tuple)
 	if (options)
 	{
 		relation->rd_options = MemoryContextAlloc(CacheMemoryContext,
-												  VARSIZE(options));
+												  VARSIZE(options),
+												  FileAndLineTag());
 		memcpy(relation->rd_options, options, VARSIZE(options));
 		pfree(options);
 	}
@@ -429,7 +430,8 @@ RelationBuildTupleDesc(Relation relation)
 	relation->rd_att->tdhasoid = relation->rd_rel->relhasoids;
 
 	constr = (TupleConstr *) MemoryContextAlloc(CacheMemoryContext,
-												sizeof(TupleConstr));
+												sizeof(TupleConstr),
+												FileAndLineTag());
 	constr->has_not_null = false;
 
 	/*
@@ -488,7 +490,8 @@ RelationBuildTupleDesc(Relation relation)
 				attrdef = (AttrDefault *)
 					MemoryContextAllocZero(CacheMemoryContext,
 										   relation->rd_rel->relnatts *
-										   sizeof(AttrDefault));
+										   sizeof(AttrDefault),
+										   FileAndLineTag());
 			attrdef[ndef].adnum = attp->attnum;
 			attrdef[ndef].adbin = NULL;
 			ndef++;
@@ -555,7 +558,8 @@ RelationBuildTupleDesc(Relation relation)
 			constr->num_check = relation->rd_rel->relchecks;
 			constr->check = (ConstrCheck *)
 				MemoryContextAllocZero(CacheMemoryContext,
-									constr->num_check * sizeof(ConstrCheck));
+									constr->num_check * sizeof(ConstrCheck),
+									FileAndLineTag());
 			CheckConstraintFetch(relation);
 		}
 		else
@@ -615,7 +619,8 @@ RelationBuildRuleLock(Relation relation)
 	 */
 	maxlocks = 4;
 	rules = (RewriteRule **)
-		MemoryContextAlloc(rulescxt, sizeof(RewriteRule *) * maxlocks);
+		MemoryContextAlloc(rulescxt, sizeof(RewriteRule *) * maxlocks,
+						   FileAndLineTag());
 	numlocks = 0;
 
 	/*
@@ -650,7 +655,8 @@ RelationBuildRuleLock(Relation relation)
 		RewriteRule *rule;
 
 		rule = (RewriteRule *) MemoryContextAlloc(rulescxt,
-												  sizeof(RewriteRule));
+												  sizeof(RewriteRule),
+												  FileAndLineTag());
 
 		rule->ruleId = HeapTupleGetOid(rewrite_tuple);
 
@@ -732,7 +738,8 @@ RelationBuildRuleLock(Relation relation)
 	/*
 	 * form a RuleLock and insert into relation
 	 */
-	rulelock = (RuleLock *) MemoryContextAlloc(rulescxt, sizeof(RuleLock));
+	rulelock = (RuleLock *) MemoryContextAlloc(rulescxt, sizeof(RuleLock),
+											   FileAndLineTag());
 	rulelock->numLocks = numlocks;
 	rulelock->rules = rules;
 
@@ -1009,7 +1016,8 @@ RelationInitIndexAccessInfo(Relation relation)
 	if (!HeapTupleIsValid(tuple))
 		elog(ERROR, "cache lookup failed for access method %u",
 			 relation->rd_rel->relam);
-	aform = (Form_pg_am) MemoryContextAlloc(CacheMemoryContext, sizeof *aform);
+	aform = (Form_pg_am) MemoryContextAlloc(CacheMemoryContext, sizeof *aform,
+											FileAndLineTag());
 	memcpy(aform, GETSTRUCT(tuple), sizeof *aform);
 	ReleaseSysCache(tuple);
 	relation->rd_am = aform;
@@ -1039,21 +1047,24 @@ RelationInitIndexAccessInfo(Relation relation)
 	 * Allocate arrays to hold data
 	 */
 	relation->rd_aminfo = (RelationAmInfo *)
-		MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo));
+		MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo),
+							   FileAndLineTag());
 
 	relation->rd_opfamily = (Oid *)
-		MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
+		MemoryContextAllocZero(indexcxt, natts * sizeof(Oid), FileAndLineTag());
 	relation->rd_opcintype = (Oid *)
-		MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
+		MemoryContextAllocZero(indexcxt, natts * sizeof(Oid), FileAndLineTag());
 
 	if (amsupport > 0)
 	{
 		int			nsupport = natts * amsupport;
 
 		relation->rd_support = (RegProcedure *)
-			MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure));
+			MemoryContextAllocZero(indexcxt, nsupport * sizeof(RegProcedure),
+								   FileAndLineTag());
 		relation->rd_supportinfo = (FmgrInfo *)
-			MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
+			MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo),
+								   FileAndLineTag());
 	}
 	else
 	{
@@ -1062,10 +1073,11 @@ RelationInitIndexAccessInfo(Relation relation)
 	}
 
 	relation->rd_indcollation = (Oid *)
-		MemoryContextAllocZero(indexcxt, natts * sizeof(Oid));
+		MemoryContextAllocZero(indexcxt, natts * sizeof(Oid), FileAndLineTag());
 
 	relation->rd_indoption = (int16 *)
-		MemoryContextAllocZero(indexcxt, natts * sizeof(int16));
+		MemoryContextAllocZero(indexcxt, natts * sizeof(int16),
+							   FileAndLineTag());
 
 	/*
 	 * indcollation cannot be referenced directly through the C struct,
@@ -1229,7 +1241,8 @@ LookupOpclassInfo(Oid operatorClassOid,
 		if (numSupport > 0)
 			opcentry->supportProcs = (RegProcedure *)
 				MemoryContextAllocZero(CacheMemoryContext,
-									   numSupport * sizeof(RegProcedure));
+									   numSupport * sizeof(RegProcedure),
+									   FileAndLineTag());
 		else
 			opcentry->supportProcs = NULL;
 	}
@@ -4091,7 +4104,8 @@ load_relcache_init_file(bool shared)
 			if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
 				goto read_failed;
 
-			opfamily = (Oid *) MemoryContextAlloc(indexcxt, len);
+			opfamily = (Oid *) MemoryContextAlloc(indexcxt, len,
+												  FileAndLineTag());
 			if (fread(opfamily, 1, len, fp) != len)
 				goto read_failed;
 
@@ -4101,7 +4115,8 @@ load_relcache_init_file(bool shared)
 			if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
 				goto read_failed;
 
-			opcintype = (Oid *) MemoryContextAlloc(indexcxt, len);
+			opcintype = (Oid *) MemoryContextAlloc(indexcxt, len,
+												   FileAndLineTag());
 			if (fread(opcintype, 1, len, fp) != len)
 				goto read_failed;
 
@@ -4110,7 +4125,8 @@ load_relcache_init_file(bool shared)
 			/* next, read the vector of support procedure OIDs */
 			if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
 				goto read_failed;
-			support = (RegProcedure *) MemoryContextAlloc(indexcxt, len);
+			support = (RegProcedure *) MemoryContextAlloc(indexcxt, len,
+														  FileAndLineTag());
 			if (fread(support, 1, len, fp) != len)
 				goto read_failed;
 
@@ -4120,7 +4136,8 @@ load_relcache_init_file(bool shared)
 			if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
 				goto read_failed;
 
-			indcollation = (Oid *) MemoryContextAlloc(indexcxt, len);
+			indcollation = (Oid *) MemoryContextAlloc(indexcxt, len,
+													  FileAndLineTag());
 			if (fread(indcollation, 1, len, fp) != len)
 				goto read_failed;
 
@@ -4130,7 +4147,8 @@ load_relcache_init_file(bool shared)
 			if (fread(&len, 1, sizeof(len), fp) != sizeof(len))
 				goto read_failed;
 
-			indoption = (int16 *) MemoryContextAlloc(indexcxt, len);
+			indoption = (int16 *) MemoryContextAlloc(indexcxt, len,
+													 FileAndLineTag());
 			if (fread(indoption, 1, len, fp) != len)
 				goto read_failed;
 
@@ -4138,10 +4156,12 @@ load_relcache_init_file(bool shared)
 
 			/* set up zeroed fmgr-info vectors */
 			rel->rd_aminfo = (RelationAmInfo *)
-				MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo));
+				MemoryContextAllocZero(indexcxt, sizeof(RelationAmInfo),
+									   FileAndLineTag());
 			nsupport = relform->relnatts * am->amsupport;
 			rel->rd_supportinfo = (FmgrInfo *)
-				MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo));
+				MemoryContextAllocZero(indexcxt, nsupport * sizeof(FmgrInfo),
+									   FileAndLineTag());
 		}
 		else
 		{
diff --git a/src/backend/utils/cache/spccache.c b/src/backend/utils/cache/spccache.c
index cf18ee1..20285ce 100644
--- a/src/backend/utils/cache/spccache.c
+++ b/src/backend/utils/cache/spccache.c
@@ -150,7 +150,8 @@ get_tablespace(Oid spcid)
 		{
 			bytea	   *bytea_opts = tablespace_reloptions(datum, false);
 
-			opts = MemoryContextAlloc(CacheMemoryContext, VARSIZE(bytea_opts));
+			opts = MemoryContextAlloc(CacheMemoryContext, VARSIZE(bytea_opts),
+									  FileAndLineTag());
 			memcpy(opts, bytea_opts, VARSIZE(bytea_opts));
 		}
 		ReleaseSysCache(tp);
diff --git a/src/backend/utils/cache/ts_cache.c b/src/backend/utils/cache/ts_cache.c
index 4ad5e7f..ea15490 100644
--- a/src/backend/utils/cache/ts_cache.c
+++ b/src/backend/utils/cache/ts_cache.c
@@ -501,7 +501,8 @@ lookup_ts_config_cache(Oid cfgId)
 					maplists[maxtokentype].len = ndicts;
 					maplists[maxtokentype].dictIds = (Oid *)
 						MemoryContextAlloc(CacheMemoryContext,
-										   sizeof(Oid) * ndicts);
+										   sizeof(Oid) * ndicts,
+										   FileAndLineTag());
 					memcpy(maplists[maxtokentype].dictIds, mapdicts,
 						   sizeof(Oid) * ndicts);
 				}
@@ -528,14 +529,15 @@ lookup_ts_config_cache(Oid cfgId)
 			maplists[maxtokentype].len = ndicts;
 			maplists[maxtokentype].dictIds = (Oid *)
 				MemoryContextAlloc(CacheMemoryContext,
-								   sizeof(Oid) * ndicts);
+								   sizeof(Oid) * ndicts, FileAndLineTag());
 			memcpy(maplists[maxtokentype].dictIds, mapdicts,
 				   sizeof(Oid) * ndicts);
 			/* and save the overall map */
 			entry->lenmap = maxtokentype + 1;
 			entry->map = (ListDictionary *)
 				MemoryContextAlloc(CacheMemoryContext,
-								   sizeof(ListDictionary) * entry->lenmap);
+								   sizeof(ListDictionary) * entry->lenmap,
+								   FileAndLineTag());
 			memcpy(entry->map, maplists,
 				   sizeof(ListDictionary) * entry->lenmap);
 		}
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 46d7eda..4c240f8 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -366,7 +366,8 @@ fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
 			finfo->fn_addr = fmgr_oldstyle;
 			fnextra = (Oldstyle_fnextra *)
 				MemoryContextAllocZero(finfo->fn_mcxt,
-									   sizeof(Oldstyle_fnextra));
+									   sizeof(Oldstyle_fnextra),
+									   FileAndLineTag());
 			finfo->fn_extra = (void *) fnextra;
 			fnextra->func = (func_ptr) user_fn;
 			for (i = 0; i < procedureStruct->pronargs; i++)
@@ -588,7 +589,8 @@ fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo,
 		Oldstyle_fnextra *fnextra;
 
 		fnextra = (Oldstyle_fnextra *)
-			MemoryContextAlloc(destcxt, sizeof(Oldstyle_fnextra));
+			MemoryContextAlloc(destcxt, sizeof(Oldstyle_fnextra),
+							   FileAndLineTag());
 		memcpy(fnextra, srcinfo->fn_extra, sizeof(Oldstyle_fnextra));
 		dstinfo->fn_extra = (void *) fnextra;
 	}
@@ -896,7 +898,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
 		MemoryContext oldcxt;
 
 		fcache = MemoryContextAllocZero(fcinfo->flinfo->fn_mcxt,
-										sizeof(*fcache));
+										sizeof(*fcache), FileAndLineTag());
 
 		fmgr_info_cxt_security(fcinfo->flinfo->fn_oid, &fcache->flinfo,
 							   fcinfo->flinfo->fn_mcxt, true);
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index dd91478..62c53aa 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -81,7 +81,7 @@ init_MultiFuncCall(PG_FUNCTION_ARGS)
 		 */
 		retval = (FuncCallContext *)
 			MemoryContextAllocZero(multi_call_ctx,
-								   sizeof(FuncCallContext));
+								   sizeof(FuncCallContext), FileAndLineTag());
 
 		/*
 		 * initialize the elements
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index 6d0e0f5..2c3320b 100644
--- a/src/backend/utils/hash/dynahash.c
+++ b/src/backend/utils/hash/dynahash.c
@@ -214,7 +214,7 @@ static void *
 DynaHashAlloc(Size size)
 {
 	Assert(MemoryContextIsValid(CurrentDynaHashCxt));
-	return MemoryContextAlloc(CurrentDynaHashCxt, size);
+	return MemoryContextAlloc(CurrentDynaHashCxt, size, FileAndLineTag());
 }
 
 
diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c
index 848c26f..6fe9794 100644
--- a/src/backend/utils/mb/mbutils.c
+++ b/src/backend/utils/mb/mbutils.c
@@ -133,7 +133,8 @@ PrepareClientEncoding(int encoding)
 		 * Load the fmgr info into TopMemoryContext (could still fail here)
 		 */
 		convinfo = (ConvProcInfo *) MemoryContextAlloc(TopMemoryContext,
-													   sizeof(ConvProcInfo));
+													   sizeof(ConvProcInfo),
+													   FileAndLineTag());
 		convinfo->s_encoding = current_server_encoding;
 		convinfo->c_encoding = encoding;
 		fmgr_info_cxt(to_server_proc, &convinfo->to_server_info,
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index d75ab43..b1a223f 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -4356,7 +4356,8 @@ push_old_value(struct config_generic * gconf, GucAction action)
 	 * We keep all the stack entries in TopTransactionContext for simplicity.
 	 */
 	stack = (GucStack *) MemoryContextAllocZero(TopTransactionContext,
-												sizeof(GucStack));
+												sizeof(GucStack),
+												FileAndLineTag());
 
 	stack->prev = gconf->stack;
 	stack->nest_level = GUCNestLevel;
diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c
index c5a331c..24d6944 100644
--- a/src/backend/utils/mmgr/aset.c
+++ b/src/backend/utils/mmgr/aset.c
@@ -64,8 +64,87 @@
 
 #include "postgres.h"
 
+#include "access/hash.h"
 #include "utils/memutils.h"
 
+struct mem_alloc_tracker {
+	const char *tag;
+	unsigned allocations;
+	unsigned bytes;
+	struct mem_alloc_tracker *next;
+};
+
+#define MEM_ALLOC_TRACKER_BUCKETS 8192
+struct mem_alloc_tracker mem_alloc_hashtab[MEM_ALLOC_TRACKER_BUCKETS];
+
+static void
+count_allocation(const char *tag, unsigned bytes)
+{
+	int		s;
+	Datum	h;
+	unsigned b;
+	struct mem_alloc_tracker *mb;
+
+	Assert(tag != NULL);
+
+	s = strlen(tag);
+	h = hash_any((const unsigned char *) tag, s);
+	b = ((uint32) h) % MEM_ALLOC_TRACKER_BUCKETS;
+	mb = &mem_alloc_hashtab[b];
+
+	if (!mb->tag)
+	{
+		mb->tag = tag;
+		mb->allocations = 1;
+		mb->bytes = bytes;
+	}
+	else if (!strcmp(mb->tag, tag))
+	{
+		mb->allocations++;
+		mb->bytes += bytes;
+	}
+	else
+	{
+		struct mem_alloc_tracker *n;
+
+		for (mb = mb->next; mb != NULL; mb = mb->next)
+		{
+			if (!strcmp(mb->tag, tag))
+			{
+				mb->allocations++;
+				mb->bytes += bytes;
+				return;
+			}
+		}
+
+		n = malloc(sizeof(struct mem_alloc_tracker));
+		n->tag = tag;
+		n->allocations = 1;
+		n->bytes = bytes;
+		n->next = mem_alloc_hashtab[b].next;
+		mem_alloc_hashtab[b].next = n;
+	}
+}
+
+void
+dump_allocations(void)
+{
+	unsigned b;
+
+	for (b = 0; b < MEM_ALLOC_TRACKER_BUCKETS; ++b)
+	{
+		struct mem_alloc_tracker *mb = &mem_alloc_hashtab[b];
+		if (!mb->tag)
+			continue;
+		while (mb != NULL)
+		{
+			write_stderr("ALLOCATE %s %u %u\n",
+						 mb->tag, mb->allocations, mb->bytes);
+			mb = mb->next;
+		}
+	}
+}
+
 /* Define this to detail debug alloc information */
 /* #define HAVE_ALLOCINFO */
 
@@ -209,9 +288,9 @@ typedef struct AllocChunkData
 /*
  * These functions implement the MemoryContext API for AllocSet contexts.
  */
-static void *AllocSetAlloc(MemoryContext context, Size size);
+static void *AllocSetAlloc(MemoryContext context, Size size, const char *tag);
 static void AllocSetFree(MemoryContext context, void *pointer);
-static void *AllocSetRealloc(MemoryContext context, void *pointer, Size size);
+static void *AllocSetRealloc(MemoryContext context, void *pointer, Size size, const char *tag);
 static void AllocSetInit(MemoryContext context);
 static void AllocSetReset(MemoryContext context);
 static void AllocSetDelete(MemoryContext context);
@@ -350,20 +429,21 @@ randomize_mem(char *ptr, size_t size)
  * maxBlockSize: maximum allocation block size
  */
 MemoryContext
-AllocSetContextCreate(MemoryContext parent,
+AllocSetContextCreate_really(MemoryContext parent,
 					  const char *name,
 					  Size minContextSize,
 					  Size initBlockSize,
-					  Size maxBlockSize)
+					  Size maxBlockSize,
+					  const char *tag)
 {
 	AllocSet	context;
 
 	/* Do the type-independent part of context creation */
-	context = (AllocSet) MemoryContextCreate(T_AllocSetContext,
+	context = (AllocSet) MemoryContextCreate_really(T_AllocSetContext,
 											 sizeof(AllocSetContext),
 											 &AllocSetMethods,
 											 parent,
-											 name);
+											 name, tag);
 
 	/*
 	 * Make sure alloc parameters are reasonable, and save them.
@@ -559,7 +639,7 @@ AllocSetDelete(MemoryContext context)
  *		to the set.
  */
 static void *
-AllocSetAlloc(MemoryContext context, Size size)
+AllocSetAlloc(MemoryContext context, Size size, const char *tag)
 {
 	AllocSet	set = (AllocSet) context;
 	AllocBlock	block;
@@ -568,6 +648,8 @@ AllocSetAlloc(MemoryContext context, Size size)
 	Size		chunk_size;
 	Size		blksize;
 
+	count_allocation(tag, size);
+
 	AssertArg(AllocSetIsValid(set));
 
 	/*
@@ -892,7 +974,7 @@ AllocSetFree(MemoryContext context, void *pointer)
  *		into the new memory, and the old memory is freed.
  */
 static void *
-AllocSetRealloc(MemoryContext context, void *pointer, Size size)
+AllocSetRealloc(MemoryContext context, void *pointer, Size size, const char *tag)
 {
 	AllocSet	set = (AllocSet) context;
 	AllocChunk	chunk = AllocPointerGetChunk(pointer);
@@ -1008,7 +1090,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
 		AllocPointer newPointer;
 
 		/* allocate new chunk */
-		newPointer = AllocSetAlloc((MemoryContext) set, size);
+		newPointer = AllocSetAlloc((MemoryContext) set, size, tag);
 
 		/* transfer existing data (certain to fit) */
 		memcpy(newPointer, pointer, oldsize);
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index 466d53d..966b164 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -507,10 +507,10 @@ MemoryContextContains(MemoryContext context, void *pointer)
  *--------------------
  */
 MemoryContext
-MemoryContextCreate(NodeTag tag, Size size,
+MemoryContextCreate_really(NodeTag tag, Size size,
 					MemoryContextMethods *methods,
 					MemoryContext parent,
-					const char *name)
+					const char *name, const char *stag)
 {
 	MemoryContext node;
 	Size		needed = size + strlen(name) + 1;
@@ -520,7 +520,7 @@ MemoryContextCreate(NodeTag tag, Size size,
 	{
 		/* Normal case: allocate the node in TopMemoryContext */
 		node = (MemoryContext) MemoryContextAlloc(TopMemoryContext,
-												  needed);
+												  needed, stag);
 	}
 	else
 	{
@@ -564,7 +564,7 @@ MemoryContextCreate(NodeTag tag, Size size,
  * nodes/memnodes.h into postgres.h which seems a bad idea.
  */
 void *
-MemoryContextAlloc(MemoryContext context, Size size)
+MemoryContextAlloc(MemoryContext context, Size size, const char *tag)
 {
 	AssertArg(MemoryContextIsValid(context));
 
@@ -574,7 +574,7 @@ MemoryContextAlloc(MemoryContext context, Size size)
 
 	context->isReset = false;
 
-	return (*context->methods->alloc) (context, size);
+	return (*context->methods->alloc) (context, size, tag);
 }
 
 /*
@@ -585,7 +585,7 @@ MemoryContextAlloc(MemoryContext context, Size size)
  *	is a very common combination, so we provide the combined operation.
  */
 void *
-MemoryContextAllocZero(MemoryContext context, Size size)
+MemoryContextAllocZero(MemoryContext context, Size size, const char *tag)
 {
 	void	   *ret;
 
@@ -597,7 +597,7 @@ MemoryContextAllocZero(MemoryContext context, Size size)
 
 	context->isReset = false;
 
-	ret = (*context->methods->alloc) (context, size);
+	ret = (*context->methods->alloc) (context, size, tag);
 
 	MemSetAligned(ret, 0, size);
 
@@ -612,7 +612,8 @@ MemoryContextAllocZero(MemoryContext context, Size size)
  *	is so often called with compile-time-constant sizes.
  */
 void *
-MemoryContextAllocZeroAligned(MemoryContext context, Size size)
+MemoryContextAllocZeroAligned(MemoryContext context, Size size,
+							  const char *tag)
 {
 	void	   *ret;
 
@@ -624,7 +625,7 @@ MemoryContextAllocZeroAligned(MemoryContext context, Size size)
 
 	context->isReset = false;
 
-	ret = (*context->methods->alloc) (context, size);
+	ret = (*context->methods->alloc) (context, size, tag);
 
 	MemSetLoop(ret, 0, size);
 
@@ -664,7 +665,7 @@ pfree(void *pointer)
  *		Adjust the size of a previously allocated chunk.
  */
 void *
-repalloc(void *pointer, Size size)
+repalloc_really(void *pointer, Size size, const char *tag)
 {
 	StandardChunkHeader *header;
 
@@ -692,7 +693,7 @@ repalloc(void *pointer, Size size)
 	Assert(!header->context->isReset);
 
 	return (*header->context->methods->realloc) (header->context,
-												 pointer, size);
+												 pointer, size, tag);
 }
 
 /*
@@ -722,12 +723,12 @@ MemoryContextSwitchTo(MemoryContext context)
  *		Like strdup(), but allocate from the specified context
  */
 char *
-MemoryContextStrdup(MemoryContext context, const char *string)
+MemoryContextStrdup_really(MemoryContext context, const char *string, const char *tag)
 {
 	char	   *nstr;
 	Size		len = strlen(string) + 1;
 
-	nstr = (char *) MemoryContextAlloc(context, len);
+	nstr = (char *) MemoryContextAlloc(context, len, tag);
 
 	memcpy(nstr, string, len);
 
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index cfb73c1..416bf2f 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -215,7 +215,8 @@ CreatePortal(const char *name, bool allowDup, bool dupSilent)
 	}
 
 	/* make new portal structure */
-	portal = (Portal) MemoryContextAllocZero(PortalMemory, sizeof *portal);
+	portal = (Portal) MemoryContextAllocZero(PortalMemory, sizeof *portal,
+											 FileAndLineTag());
 
 	/* initialize portal heap context; typically it won't store much */
 	portal->heap = AllocSetContextCreate(PortalMemory,
diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c
index 7c771eb..c9e36a9 100644
--- a/src/backend/utils/resowner/resowner.c
+++ b/src/backend/utils/resowner/resowner.c
@@ -130,7 +130,8 @@ ResourceOwnerCreate(ResourceOwner parent, const char *name)
 	ResourceOwner owner;
 
 	owner = (ResourceOwner) MemoryContextAllocZero(TopMemoryContext,
-												   sizeof(ResourceOwnerData));
+												   sizeof(ResourceOwnerData),
+												   FileAndLineTag());
 	owner->name = name;
 
 	if (parent)
@@ -467,7 +468,8 @@ RegisterResourceReleaseCallback(ResourceReleaseCallback callback, void *arg)
 
 	item = (ResourceReleaseCallbackItem *)
 		MemoryContextAlloc(TopMemoryContext,
-						   sizeof(ResourceReleaseCallbackItem));
+						   sizeof(ResourceReleaseCallbackItem),
+						   FileAndLineTag());
 	item->callback = callback;
 	item->arg = arg;
 	item->next = ResourceRelease_callbacks;
@@ -519,7 +521,8 @@ ResourceOwnerEnlargeBuffers(ResourceOwner owner)
 	{
 		newmax = 16;
 		owner->buffers = (Buffer *)
-			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(Buffer));
+			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(Buffer),
+							   FileAndLineTag());
 		owner->maxbuffers = newmax;
 	}
 	else
@@ -607,7 +610,8 @@ ResourceOwnerEnlargeCatCacheRefs(ResourceOwner owner)
 	{
 		newmax = 16;
 		owner->catrefs = (HeapTuple *)
-			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(HeapTuple));
+			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(HeapTuple),
+							   FileAndLineTag());
 		owner->maxcatrefs = newmax;
 	}
 	else
@@ -678,7 +682,8 @@ ResourceOwnerEnlargeCatCacheListRefs(ResourceOwner owner)
 	{
 		newmax = 16;
 		owner->catlistrefs = (CatCList **)
-			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(CatCList *));
+			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(CatCList *),
+							   FileAndLineTag());
 		owner->maxcatlistrefs = newmax;
 	}
 	else
@@ -749,7 +754,8 @@ ResourceOwnerEnlargeRelationRefs(ResourceOwner owner)
 	{
 		newmax = 16;
 		owner->relrefs = (Relation *)
-			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(Relation));
+			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(Relation),
+							   FileAndLineTag());
 		owner->maxrelrefs = newmax;
 	}
 	else
@@ -830,7 +836,8 @@ ResourceOwnerEnlargePlanCacheRefs(ResourceOwner owner)
 	{
 		newmax = 16;
 		owner->planrefs = (CachedPlan **)
-			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(CachedPlan *));
+			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(CachedPlan *),
+							   FileAndLineTag());
 		owner->maxplanrefs = newmax;
 	}
 	else
@@ -910,7 +917,8 @@ ResourceOwnerEnlargeTupleDescs(ResourceOwner owner)
 	{
 		newmax = 16;
 		owner->tupdescs = (TupleDesc *)
-			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(TupleDesc));
+			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(TupleDesc),
+							   FileAndLineTag());
 		owner->maxtupdescs = newmax;
 	}
 	else
@@ -992,7 +1000,8 @@ ResourceOwnerEnlargeSnapshots(ResourceOwner owner)
 	{
 		newmax = 16;
 		owner->snapshots = (Snapshot *)
-			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(Snapshot));
+			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(Snapshot),
+							   FileAndLineTag());
 		owner->maxsnapshots = newmax;
 	}
 	else
@@ -1075,7 +1084,8 @@ ResourceOwnerEnlargeFiles(ResourceOwner owner)
 	{
 		newmax = 16;
 		owner->files = (File *)
-			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(File));
+			MemoryContextAlloc(TopMemoryContext, newmax * sizeof(File),
+							   FileAndLineTag());
 		owner->maxfiles = newmax;
 	}
 	else
diff --git a/src/backend/utils/sort/sortsupport.c b/src/backend/utils/sort/sortsupport.c
index 7f388fd..5bf6ede 100644
--- a/src/backend/utils/sort/sortsupport.c
+++ b/src/backend/utils/sort/sortsupport.c
@@ -111,7 +111,8 @@ PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup)
 	SortShimExtra   *extra;
 
 	extra = (SortShimExtra *) MemoryContextAlloc(ssup->ssup_cxt,
-												 sizeof(SortShimExtra));
+												 sizeof(SortShimExtra),
+												 FileAndLineTag());
 
 	/* Lookup the comparison function */
 	fmgr_info_cxt(cmpFunc, &extra->flinfo, ssup->ssup_cxt);
diff --git a/src/backend/utils/time/combocid.c b/src/backend/utils/time/combocid.c
index 5429922..ad1bf3d 100644
--- a/src/backend/utils/time/combocid.c
+++ b/src/backend/utils/time/combocid.c
@@ -221,7 +221,8 @@ GetComboCommandId(CommandId cmin, CommandId cmax)
 
 		comboCids = (ComboCidKeyData *)
 			MemoryContextAlloc(TopTransactionContext,
-							   sizeof(ComboCidKeyData) * CCID_ARRAY_SIZE);
+							   sizeof(ComboCidKeyData) * CCID_ARRAY_SIZE,
+							   FileAndLineTag());
 		sizeComboCids = CCID_ARRAY_SIZE;
 		usedComboCids = 0;
 	}
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index 574099d..080f76c 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -325,7 +325,8 @@ CopySnapshot(Snapshot snapshot)
 	if (snapshot->subxcnt > 0)
 		size += snapshot->subxcnt * sizeof(TransactionId);
 
-	newsnap = (Snapshot) MemoryContextAlloc(TopTransactionContext, size);
+	newsnap = (Snapshot) MemoryContextAlloc(TopTransactionContext, size,
+										    FileAndLineTag());
 	memcpy(newsnap, snapshot, sizeof(SnapshotData));
 
 	newsnap->regd_count = 0;
@@ -390,7 +391,9 @@ PushActiveSnapshot(Snapshot snap)
 
 	Assert(snap != InvalidSnapshot);
 
-	newactive = MemoryContextAlloc(TopTransactionContext, sizeof(ActiveSnapshotElt));
+	newactive = MemoryContextAlloc(TopTransactionContext,
+								   sizeof(ActiveSnapshotElt),
+								   FileAndLineTag());
 
 	/*
 	 * Checking SecondarySnapshot is probably useless here, but it seems
diff --git a/src/include/nodes/bitmapset.h b/src/include/nodes/bitmapset.h
index bcca70d..bc1b9fe 100644
--- a/src/include/nodes/bitmapset.h
+++ b/src/include/nodes/bitmapset.h
@@ -58,9 +58,14 @@ typedef enum
  * function prototypes in nodes/bitmapset.c
  */
 
-extern Bitmapset *bms_copy(const Bitmapset *a);
+#define bms_make_singleton(x) \
+	bms_make_singleton_really(x, FileAndLineTag())
+#define bms_copy(x) \
+	bms_copy_really(x, FileAndLineTag())
+
+extern Bitmapset *bms_copy_really(const Bitmapset *a, const char *tag);
 extern bool bms_equal(const Bitmapset *a, const Bitmapset *b);
-extern Bitmapset *bms_make_singleton(int x);
+extern Bitmapset *bms_make_singleton_really(int x, const char *tag);
 extern void bms_free(Bitmapset *a);
 
 extern Bitmapset *bms_union(const Bitmapset *a, const Bitmapset *b);
@@ -80,9 +85,13 @@ extern bool bms_is_empty(const Bitmapset *a);
 
 /* these routines recycle (modify or free) their non-const inputs: */
 
-extern Bitmapset *bms_add_member(Bitmapset *a, int x);
+#define bms_add_member(a, x) bms_add_member_really(a, x, FileAndLineTag())
+#define bms_add_members(a, b) bms_add_members_really(a, b, FileAndLineTag())
+
+extern Bitmapset *bms_add_member_really(Bitmapset *a, int x, const char *tag);
 extern Bitmapset *bms_del_member(Bitmapset *a, int x);
-extern Bitmapset *bms_add_members(Bitmapset *a, const Bitmapset *b);
+extern Bitmapset *bms_add_members_really(Bitmapset *a, const Bitmapset *b,
+		const char *tag);
 extern Bitmapset *bms_int_members(Bitmapset *a, const Bitmapset *b);
 extern Bitmapset *bms_del_members(Bitmapset *a, const Bitmapset *b);
 extern Bitmapset *bms_join(Bitmapset *a, Bitmapset *b);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index a6dffe6..c9f78da 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -23,25 +23,35 @@ extern A_Expr *makeA_Expr(A_Expr_Kind kind, List *name,
 extern A_Expr *makeSimpleA_Expr(A_Expr_Kind kind, char *name,
 				 Node *lexpr, Node *rexpr, int location);
 
-extern Var *makeVar(Index varno,
+#define makeVar(a, b, c, d, e, f) \
+	makeVar_really(a, b, c, d, e, f, FileAndLineTag())
+
+extern Var *makeVar_really(Index varno,
 		AttrNumber varattno,
 		Oid vartype,
 		int32 vartypmod,
 		Oid varcollid,
-		Index varlevelsup);
+		Index varlevelsup, const char *tag);
+
+#define makeVarFromTargetEntry(a, b) \
+	makeVarFromTargetEntry_really(a, b, FileAndLineTag())
 
-extern Var *makeVarFromTargetEntry(Index varno,
-					   TargetEntry *tle);
+extern Var *makeVarFromTargetEntry_really(Index varno,
+					   TargetEntry *tle, const char *tag);
 
 extern Var *makeWholeRowVar(RangeTblEntry *rte,
 				Index varno,
 				Index varlevelsup,
 				bool allowScalar);
 
-extern TargetEntry *makeTargetEntry(Expr *expr,
+#define makeTargetEntry(a, b, c, d) \
+	makeTargetEntry_really(a, b, c, d, FileAndLineTag())
+
+extern TargetEntry *makeTargetEntry_really(Expr *expr,
 				AttrNumber resno,
 				char *resname,
-				bool resjunk);
+				bool resjunk,
+				const char *tag);
 
 extern TargetEntry *flatCopyTargetEntry(TargetEntry *src_tle);
 
diff --git a/src/include/nodes/memnodes.h b/src/include/nodes/memnodes.h
index 503d59f..f1bb843 100644
--- a/src/include/nodes/memnodes.h
+++ b/src/include/nodes/memnodes.h
@@ -35,10 +35,10 @@
 
 typedef struct MemoryContextMethods
 {
-	void	   *(*alloc) (MemoryContext context, Size size);
+	void	   *(*alloc) (MemoryContext context, Size size, const char *tag);
 	/* call this free_p in case someone #define's free() */
 	void		(*free_p) (MemoryContext context, void *pointer);
-	void	   *(*realloc) (MemoryContext context, void *pointer, Size size);
+	void	   *(*realloc) (MemoryContext context, void *pointer, Size size, const char *tag);
 	void		(*init) (MemoryContext context);
 	void		(*reset) (MemoryContext context);
 	void		(*delete_context) (MemoryContext context);
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 1e16088..516a123 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -447,10 +447,10 @@ typedef struct Node
 #ifdef __GNUC__
 
 /* With GCC, we can use a compound statement within an expression */
-#define newNode(size, tag) \
+#define newNode(size, tag, stag) \
 ({	Node   *_result; \
 	AssertMacro((size) >= sizeof(Node));		/* need the tag, at least */ \
-	_result = (Node *) palloc0fast(size); \
+	_result = (Node *) palloc0fastwithtag(size, stag); \
 	_result->type = (tag); \
 	_result; \
 })
@@ -464,17 +464,18 @@ typedef struct Node
  */
 extern PGDLLIMPORT Node *newNodeMacroHolder;
 
-#define newNode(size, tag) \
+#define newNode(size, tag, stag) \
 ( \
 	AssertMacro((size) >= sizeof(Node)),		/* need the tag, at least */ \
-	newNodeMacroHolder = (Node *) palloc0fast(size), \
+	newNodeMacroHolder = (Node *) palloc0fastwithtag(size, stag), \
 	newNodeMacroHolder->type = (tag), \
 	newNodeMacroHolder \
 )
 #endif   /* __GNUC__ */
 
 
-#define makeNode(_type_)		((_type_ *) newNode(sizeof(_type_),T_##_type_))
+#define makeNode(_type_)		((_type_ *) newNode(sizeof(_type_),T_##_type_,FileAndLineTag()))
+#define makeNodeWithTag(_type_,_tag_)	((_type_ *) newNode(sizeof(_type_),T_##_type_,_tag_))
 #define NodeSetTag(nodeptr,t)	(((Node*)(nodeptr))->type = (t))
 
 #define IsA(nodeptr,_type_)		(nodeTag(nodeptr) == T_##_type_)
diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h
index 15b86dd..344c095 100644
--- a/src/include/nodes/pg_list.h
+++ b/src/include/nodes/pg_list.h
@@ -136,6 +136,10 @@ extern int	list_length(const List *l);
 #define llast_int(l)			lfirst_int(list_tail(l))
 #define llast_oid(l)			lfirst_oid(list_tail(l))
 
+#define lcons(d, l) lcons_really(d, l, FileAndLineTag())
+#define lcons_int(d, l) lcons_int_really(d, l, FileAndLineTag())
+#define lcons_oid(d, l) lcons_oid_really(d, l, FileAndLineTag())
+
 /*
  * Convenience macros for building fixed-length lists
  */
@@ -191,17 +195,21 @@ extern int	list_length(const List *l);
 		 (cell1) != NULL && (cell2) != NULL && (cell3) != NULL;		\
 		 (cell1) = lnext(cell1), (cell2) = lnext(cell2), (cell3) = lnext(cell3))
 
-extern List *lappend(List *list, void *datum);
-extern List *lappend_int(List *list, int datum);
-extern List *lappend_oid(List *list, Oid datum);
+extern List *lappend_really(List *list, void *datum, const char *tag);
+extern List *lappend_int_really(List *list, int datum, const char *tag);
+extern List *lappend_oid_really(List *list, Oid datum, const char *tag);
+
+#define lappend(l, d) lappend_really(l, d, FileAndLineTag())
+#define lappend_int(l, d) lappend_int_really(l, d, FileAndLineTag())
+#define lappend_oid(l, d) lappend_oid_really(l, d, FileAndLineTag())
 
 extern ListCell *lappend_cell(List *list, ListCell *prev, void *datum);
 extern ListCell *lappend_cell_int(List *list, ListCell *prev, int datum);
 extern ListCell *lappend_cell_oid(List *list, ListCell *prev, Oid datum);
 
-extern List *lcons(void *datum, List *list);
-extern List *lcons_int(int datum, List *list);
-extern List *lcons_oid(Oid datum, List *list);
+extern List *lcons_really(void *datum, List *list, const char *tag);
+extern List *lcons_int_really(int datum, List *list, const char *tag);
+extern List *lcons_oid_really(Oid datum, List *list, const char *tag);
 
 extern List *list_concat(List *list1, List *list2);
 extern List *list_truncate(List *list, int new_size);
@@ -236,10 +244,23 @@ extern List *list_difference_ptr(const List *list1, const List *list2);
 extern List *list_difference_int(const List *list1, const List *list2);
 extern List *list_difference_oid(const List *list1, const List *list2);
 
-extern List *list_append_unique(List *list, void *datum);
-extern List *list_append_unique_ptr(List *list, void *datum);
-extern List *list_append_unique_int(List *list, int datum);
-extern List *list_append_unique_oid(List *list, Oid datum);
+extern List *list_append_unique_really(List *list, void *datum,
+									   const char *tag);
+extern List *list_append_unique_ptr_really(List *list, void *datum,
+										   const char *tag);
+extern List *list_append_unique_int_really(List *list, int datum,
+										   const char *tag);
+extern List *list_append_unique_oid_really(List *list, Oid datum,
+										   const char *tag);
+
+#define list_append_unique(l, d) \
+	list_append_unique_really(l, d, FileAndLineTag())
+#define list_append_unique_ptr(l, d) \
+	list_append_unique_ptr_really(l, d, FileAndLineTag())
+#define list_append_unique_int(l, d) \
+	list_append_unique_int_really(l, d, FileAndLineTag())
+#define list_append_unique_oid(l, d) \
+	list_append_unique_oid_really(l, d, FileAndLineTag())
 
 extern List *list_concat_unique(List *list1, List *list2);
 extern List *list_concat_unique_ptr(List *list1, List *list2);
@@ -249,8 +270,12 @@ extern List *list_concat_unique_oid(List *list1, List *list2);
 extern void list_free(List *list);
 extern void list_free_deep(List *list);
 
-extern List *list_copy(const List *list);
-extern List *list_copy_tail(const List *list, int nskip);
+#define list_copy(l) list_copy_really(l, FileAndLineTag())
+#define list_copy_tail(l, n) list_copy_tail_really(l, n, FileAndLineTag())
+
+extern List *list_copy_really(const List *list, const char *tag);
+extern List *list_copy_tail_really(const List *list, int nskip,
+								   const char *tag);
 
 /*
  * To ease migration to the new list API, a set of compatibility
diff --git a/src/include/nodes/value.h b/src/include/nodes/value.h
index 523a906..d643a0a 100644
--- a/src/include/nodes/value.h
+++ b/src/include/nodes/value.h
@@ -53,9 +53,11 @@ typedef struct Value
 #define floatVal(v)		atof(((Value *)(v))->val.str)
 #define strVal(v)		(((Value *)(v))->val.str)
 
+#define makeString(x) makeString_really(x, FileAndLineTag())
+
 extern Value *makeInteger(long i);
 extern Value *makeFloat(char *numericStr);
-extern Value *makeString(char *str);
+extern Value *makeString_really(char *str, const char *tag);
 extern Value *makeBitString(char *str);
 
 #endif   /* VALUE_H */
diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h
index a2bb3d9..4163873 100644
--- a/src/include/utils/memutils.h
+++ b/src/include/utils/memutils.h
@@ -108,10 +108,14 @@ extern bool MemoryContextContains(MemoryContext context, void *pointer);
  * context creation.  It's intended to be called from context-type-
  * specific creation routines, and noplace else.
  */
-extern MemoryContext MemoryContextCreate(NodeTag tag, Size size,
+
+#define MemoryContextCreate(a, b, c, d, e) \
+	MemoryContextCreate_really(a, b, c, d, e, FileAndLineTag())
+
+extern MemoryContext MemoryContextCreate_really(NodeTag tag, Size size,
 					MemoryContextMethods *methods,
 					MemoryContext parent,
-					const char *name);
+					const char *name, const char *stag);
 
 
 /*
@@ -119,11 +123,14 @@ extern MemoryContext MemoryContextCreate(NodeTag tag, Size size,
  */
 
 /* aset.c */
-extern MemoryContext AllocSetContextCreate(MemoryContext parent,
+#define AllocSetContextCreate(a, b, c, d, e) \
+	AllocSetContextCreate_really(a, b, c, d, e, FileAndLineTag())
+
+extern MemoryContext AllocSetContextCreate_really(MemoryContext parent,
 					  const char *name,
 					  Size minContextSize,
 					  Size initBlockSize,
-					  Size maxBlockSize);
+					  Size maxBlockSize, const char *tag);
 
 /*
  * Recommended default alloc parameters, suitable for "ordinary" contexts
@@ -141,4 +148,6 @@ extern MemoryContext AllocSetContextCreate(MemoryContext parent,
 #define ALLOCSET_SMALL_INITSIZE  (1 * 1024)
 #define ALLOCSET_SMALL_MAXSIZE	 (8 * 1024)
 
+extern void dump_allocations(void);
+
 #endif   /* MEMUTILS_H */
diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h
index 973f306..277f5cc 100644
--- a/src/include/utils/palloc.h
+++ b/src/include/utils/palloc.h
@@ -45,13 +45,16 @@ extern PGDLLIMPORT MemoryContext CurrentMemoryContext;
 /*
  * Fundamental memory-allocation operations (more are in utils/memutils.h)
  */
-extern void *MemoryContextAlloc(MemoryContext context, Size size);
-extern void *MemoryContextAllocZero(MemoryContext context, Size size);
-extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
+extern void *MemoryContextAlloc(MemoryContext context, Size size, const char *tag);
+extern void *MemoryContextAllocZero(MemoryContext context, Size size, const char *tag);
+extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size, const char *tag);
 
-#define palloc(sz)	MemoryContextAlloc(CurrentMemoryContext, (sz))
+#define CppMacroAsString(x)			CppAsString(x)
+#define FileAndLineTag()			(__FILE__ ":" CppMacroAsString(__LINE__))
 
-#define palloc0(sz) MemoryContextAllocZero(CurrentMemoryContext, (sz))
+#define palloc(sz)	MemoryContextAlloc(CurrentMemoryContext, (sz), FileAndLineTag())
+
+#define palloc0(sz) MemoryContextAllocZero(CurrentMemoryContext, (sz), FileAndLineTag())
 
 /*
  * The result of palloc() is always word-aligned, so we can skip testing
@@ -63,12 +66,19 @@ extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
  */
 #define palloc0fast(sz) \
 	( MemSetTest(0, sz) ? \
-		MemoryContextAllocZeroAligned(CurrentMemoryContext, sz) : \
-		MemoryContextAllocZero(CurrentMemoryContext, sz) )
+		MemoryContextAllocZeroAligned(CurrentMemoryContext, sz, FileAndLineTag()) : \
+		MemoryContextAllocZero(CurrentMemoryContext, sz, FileAndLineTag()) )
+
+#define palloc0fastwithtag(sz, tag) \
+	( MemSetTest(0, sz) ? \
+		MemoryContextAllocZeroAligned(CurrentMemoryContext, sz, tag) : \
+		MemoryContextAllocZero(CurrentMemoryContext, sz, tag) )
 
 extern void pfree(void *pointer);
 
-extern void *repalloc(void *pointer, Size size);
+extern void *repalloc_really(void *pointer, Size size, const char *tag);
+
+#define repalloc(p, s) repalloc_really(p, s, FileAndLineTag())
 
 /*
  * MemoryContextSwitchTo can't be a macro in standard C compilers.
@@ -97,8 +107,9 @@ extern MemoryContext MemoryContextSwitchTo(MemoryContext context);
  * These are like standard strdup() except the copied string is
  * allocated in a context, not with malloc().
  */
-extern char *MemoryContextStrdup(MemoryContext context, const char *string);
+extern char *MemoryContextStrdup_really(MemoryContext context, const char *string, const char *tag);
 
+#define MemoryContextStrdup(a, b)  MemoryContextStrdup_really(a, b, FileAndLineTag())
 #define pstrdup(str)  MemoryContextStrdup(CurrentMemoryContext, (str))
 
 extern char *pnstrdup(const char *in, Size len);
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index d43b8e0..68adf0b 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -321,7 +321,8 @@ do_compile(FunctionCallInfo fcinfo,
 	if (function == NULL)
 	{
 		function = (PLpgSQL_function *)
-			MemoryContextAllocZero(TopMemoryContext, sizeof(PLpgSQL_function));
+			MemoryContextAllocZero(TopMemoryContext, sizeof(PLpgSQL_function),
+								   FileAndLineTag());
 	}
 	else
 	{
@@ -364,7 +365,8 @@ do_compile(FunctionCallInfo fcinfo,
 	plpgsql_nDatums = 0;
 	/* This is short-lived, so needn't allocate in function's cxt */
 	plpgsql_Datums = MemoryContextAlloc(compile_tmp_cxt,
-									 sizeof(PLpgSQL_datum *) * datums_alloc);
+									 sizeof(PLpgSQL_datum *) * datums_alloc,
+									 FileAndLineTag());
 	datums_last = 0;
 
 	switch (is_trigger)
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 95e74b3..16dd5ef 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -5909,7 +5909,8 @@ plpgsql_create_econtext(PLpgSQL_execstate *estate)
 	 */
 	entry = (SimpleEcontextStackEntry *)
 		MemoryContextAlloc(TopTransactionContext,
-						   sizeof(SimpleEcontextStackEntry));
+						   sizeof(SimpleEcontextStackEntry),
+						   FileAndLineTag());
 
 	entry->stack_econtext = estate->eval_econtext;
 	entry->xact_subxid = GetCurrentSubTransactionId();
diff --git a/src/pl/plpython/plpy_util.c b/src/pl/plpython/plpy_util.c
index 414b9d5..f95bffb 100644
--- a/src/pl/plpython/plpy_util.c
+++ b/src/pl/plpython/plpy_util.c
@@ -21,7 +21,7 @@ void *
 PLy_malloc(size_t bytes)
 {
 	/* We need our allocations to be long-lived, so use TopMemoryContext */
-	return MemoryContextAlloc(TopMemoryContext, bytes);
+	return MemoryContextAlloc(TopMemoryContext, bytes, FileAndLineTag());
 }
 
 void *
#2Heikki Linnakangas
heikki.linnakangas@enterprisedb.com
In reply to: Robert Haas (#1)
Re: counting pallocs

On 17.05.2012 06:43, Robert Haas wrote:

The attached patch provides some rough instrumentation for determining
where palloc calls are coming from. This is obviously just for
noodling around with, not for commit, and there may well be bugs. But
enjoy.

I gave this a quick spin on a couple of test workloads: a very short
pgbench test, a very short pgbench -S test, and the regression tests.
On the pgbench test, the top culprits are ExecInitExpr() and
expression_tree_mutator(); in both cases, the lappend() call for the
T_List case is the major contributor. Other significant contributors
include _copyVar(), which I haven't drilled into terribly far but
seems to be coming mostly from add_vars_to_targetlist();
buildRelationAliases() via lappend, pstrdup, and makeString;
ExecAllocTupleTableSlot(); and makeColumnRef() via makeNode, lcons,
and makeString.

What percentage of total CPU usage is the palloc() overhead in these
tests? If we could totally eliminate the palloc() overhead, how much
faster would the test run?

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

#3Robert Haas
robertmhaas@gmail.com
In reply to: Heikki Linnakangas (#2)
Re: counting pallocs

On Thu, May 17, 2012 at 2:28 AM, Heikki Linnakangas
<heikki.linnakangas@enterprisedb.com> wrote:

What percentage of total CPU usage is the palloc() overhead in these tests?
If we could totally eliminate the palloc() overhead, how much faster would
the test run?

AllocSetAlloc is often the top CPU consumer in profiling results, but
it's typically only in the single-digit percentages. However, there's
also some distributed overhead that's more difficult to measure. For
example, the fact that OpExpr uses a List instead of directly pointing
to its arguments costs us three pallocs - plus three more if we ever
copy it - but it also means that accessing the first element of an
OpExpr requires three pointer dereferences instead of one, and
accessing the second one requires four pointer dereferences instead of
one. There's no real way to isolate the overhead of that, but it's
got to cost at least something.

The reality - I'm not sure whether it's a happy reality or a sad
reality - is that most CPU profiles of PostgreSQL are pretty flat.
The nails that stick up have, for the most part, long since been
pounded down. If we want to make further improvements to our parse
and plan time, and I do, because I think we lag our competitors, then
I think this is the kind of stuff we need to look at.

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

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Robert Haas (#1)
Re: counting pallocs

Robert Haas <robertmhaas@gmail.com> writes:

One piece of reasonably low-hanging fruit appears to be OpExpr. It
seems like it would be better all around to put Node *arg1 and Node
*arg2 in there instead of a list... aside from saving pallocs, it
seems like it would generally simplify the code.

Obviously, Stephen Frost's list-allocation patch would affect your
results here ... but I wonder how much the above change would affect
*his* results. Specifically, the observation that most lists are 1
or 2 elements long would presumably become less true, but I wonder
by how much exactly.

regards, tom lane