diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index b6ec32b..ba57118 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -47,6 +47,8 @@
 #include "rewrite/rewriteManip.h"
 #include "utils/lsyscache.h"
 #include "utils/rel.h"
+#include "utils/memutils.h"
+#include "nodes/memnodes.h"
 
 
 /* results of subquery_is_pushdown_safe */
@@ -3092,6 +3094,10 @@ generate_partition_wise_join_paths(PlannerInfo *root, RelOptInfo *rel)
 	int		num_dummy_parts;
 	ListCell   *lc;
 
+	MemoryContextCounters mem_start;
+ 
+	MemoryContextFuncStatsStart(CurrentMemoryContext, &mem_start, __FUNCTION__);
+
 	/* Handle only join relations. */
 	if (!IS_JOIN_REL(rel))
 		return;
@@ -3211,6 +3217,8 @@ generate_partition_wise_join_paths(PlannerInfo *root, RelOptInfo *rel)
 
 	if (sampled_children)
 		list_free(sampled_children);
+
+	MemoryContextFuncStatsEnd(CurrentMemoryContext, &mem_start, __FUNCTION__);
 }
 
 /*****************************************************************************
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index b4220eb..ded1b7e 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -23,6 +23,7 @@
 #include "optimizer/prep.h"
 #include "optimizer/cost.h"
 #include "utils/memutils.h"
+#include "nodes/memnodes.h"
 
 
 static void make_rels_by_clause_joins(PlannerInfo *root,
@@ -766,6 +767,13 @@ populate_joinrel_with_paths(PlannerInfo *root, RelOptInfo *rel1,
 							RelOptInfo *rel2, RelOptInfo *joinrel,
 							SpecialJoinInfo *sjinfo, List *restrictlist)
 {
+	MemoryContextCounters mem_start;
+	char *label;
+
+	label = joinrel->reloptkind == RELOPT_OTHER_JOINREL ? "child_join_path_creation" : "parent_join_path_creation";
+
+	MemoryContextFuncStatsStart(CurrentMemoryContext, &mem_start, label);
+
 	/*
 	 * Consider paths using each rel as both outer and inner.  Depending on
 	 * the join type, a provably empty outer or inner rel might mean the join
@@ -910,6 +918,8 @@ populate_joinrel_with_paths(PlannerInfo *root, RelOptInfo *rel1,
 			elog(ERROR, "unrecognized join type: %d", (int) sjinfo->jointype);
 			break;
 	}
+
+	MemoryContextFuncStatsEnd(CurrentMemoryContext, &mem_start, label);
 }
 
 /*
@@ -1322,6 +1332,10 @@ try_partition_wise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
 	int		cnt_parts;
 	PartitionScheme		part_scheme;
 	PartitionedJoin	   *partitioned_join;
+	MemoryContextCounters start_mem;
+
+	/* Start measuring memory */
+	MemoryContextFuncStatsStart(CurrentMemoryContext, &start_mem, __FUNCTION__);
 
 	/* Guard against stack overflow due to overly deep partition hierarchy. */
 	check_stack_depth();
@@ -1415,6 +1429,7 @@ try_partition_wise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
 		List	   *join_appinfos;
 		List	   *appinfos1;
 		List	   *appinfos2;
+		MemoryContextCounters restrict_mem;
 
 		/* We should never try to join two overlapping sets of rels. */
 		Assert(!bms_overlap(child_rel1->relids, child_rel2->relids));
@@ -1431,6 +1446,7 @@ try_partition_wise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
 		appinfos2 = find_appinfos_by_relids(root, child_rel2->relids);
 		join_appinfos = list_concat(appinfos1, appinfos2);
 
+		MemoryContextFuncStatsStart(CurrentMemoryContext, &restrict_mem, "restrictlist translation");
 		/*
 		 * Construct restrictions applicable to the child join from
 		 * those applicable to the parent join.
@@ -1439,6 +1455,8 @@ try_partition_wise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
 												   (Node *)parent_restrictlist,
 																join_appinfos);
 
+		MemoryContextFuncStatsEnd(CurrentMemoryContext, &restrict_mem, "restrictlist translation");
+
 		/*
 		 * Construct SpecialJoinInfo from parent join relations's
 		 * SpecialJoinInfo.
@@ -1462,6 +1480,9 @@ try_partition_wise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
 		try_partition_wise_join(root, child_rel1, child_rel2, child_joinrel,
 								child_sjinfo, child_restrictlist);
 	}
+
+	/* Stop measuring memory and print the stats. */
+	MemoryContextFuncStatsEnd(CurrentMemoryContext, &start_mem, __FUNCTION__);
 }
 
 /*
@@ -1481,6 +1502,7 @@ add_paths_to_child_joinrel(PlannerInfo *root, RelOptInfo *parent_joinrel,
 {
 	ListCell	*lc;
 	RelOptInfo	   *child_joinrel = parent_joinrel->part_rels[child_id];
+	MemoryContextCounters rest_mem_usage;
 
 	Assert(IS_JOIN_REL(parent_joinrel));
 
@@ -1531,6 +1553,7 @@ add_paths_to_child_joinrel(PlannerInfo *root, RelOptInfo *parent_joinrel,
 		child_sjinfo = build_child_join_sjinfo(root, pj->sjinfo, appinfos1,
 											   appinfos2);
 
+		MemoryContextFuncStatsStart(CurrentMemoryContext, &rest_mem_usage, "restrictlist translation");
 		/*
 		 * Construct restrictions applicable to the child join from
 		 * those applicable to the parent join.
@@ -1539,6 +1562,8 @@ add_paths_to_child_joinrel(PlannerInfo *root, RelOptInfo *parent_joinrel,
 													 (Node *) pj->restrictlist,
 																join_appinfos);
 
+		MemoryContextFuncStatsEnd(CurrentMemoryContext, &rest_mem_usage, "restrictlist translation");
+
 		/* The list is not needed anymore. */
 		list_free(join_appinfos);
 
@@ -1565,8 +1590,11 @@ static SpecialJoinInfo *
 build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
 							List *append_rel_infos1, List *append_rel_infos2)
 {
-	SpecialJoinInfo *sjinfo = copyObject(parent_sjinfo);
+	MemoryContextCounters mem_start;
+	SpecialJoinInfo *sjinfo;
 
+	MemoryContextFuncStatsStart(CurrentMemoryContext, &mem_start, __FUNCTION__);
+	sjinfo = copyObject(parent_sjinfo);
 	sjinfo->min_lefthand = adjust_child_relids(sjinfo->min_lefthand,
 											   append_rel_infos1);
 	sjinfo->min_righthand = adjust_child_relids(sjinfo->min_righthand,
@@ -1580,6 +1608,8 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
 	sjinfo->semi_rhs_exprs = (List *) adjust_join_appendrel_attrs(root,
 											   (Node *) sjinfo->semi_rhs_exprs,
 															append_rel_infos2);
+
+	MemoryContextFuncStatsEnd(CurrentMemoryContext, &mem_start, __FUNCTION__);
 	return sjinfo;
 }
 
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 3c0898a..e9ada93 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -55,6 +55,8 @@
 #include "utils/selfuncs.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
+#include "nodes/memnodes.h"
+#include "utils/memutils.h"
 
 
 /* GUC parameters */
@@ -192,6 +194,9 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
 	Plan	   *top_plan;
 	ListCell   *lp,
 			   *lr;
+	MemoryContextCounters mem_start;
+
+	MemoryContextFuncStatsStart(CurrentMemoryContext, &mem_start, __FUNCTION__);
 
 	/* Cursor options may come from caller or from DECLARE CURSOR stmt */
 	if (parse->utilityStmt &&
@@ -432,6 +437,8 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
 	result->invalItems = glob->invalItems;
 	result->nParamExec = glob->nParamExec;
 
+	MemoryContextFuncStatsEnd(CurrentMemoryContext, &mem_start, __FUNCTION__);
+
 	return result;
 }
 
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 8510775..c27c59b 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -30,6 +30,8 @@
 #include "parser/parsetree.h"
 #include "utils/lsyscache.h"
 #include "utils/selfuncs.h"
+#include "utils/memutils.h"
+#include "nodes/memnodes.h"
 
 
 typedef enum
@@ -3390,6 +3392,9 @@ reparameterize_path_by_child(PlannerInfo *root, Path *path,
 	ParamPathInfo   *new_ppi;
 	ParamPathInfo   *old_ppi;
 	List	   *child_aris;
+	MemoryContextCounters	mem_start;
+
+	MemoryContextFuncStatsStart(CurrentMemoryContext, &mem_start, __FUNCTION__);
 
 	/*
 	 * If the path is not parameterized by parent of the given relation, it
@@ -3520,5 +3525,7 @@ reparameterize_path_by_child(PlannerInfo *root, Path *path,
 			break;
 	}
 
+	MemoryContextFuncStatsEnd(CurrentMemoryContext, &mem_start, __FUNCTION__);
+
 	return new_path;
 }
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index be08b6e..5d00c85 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -31,6 +31,8 @@
 #include "rewrite/rewriteManip.h"
 #include "utils/hsearch.h"
 #include "utils/rel.h"
+#include "nodes/memnodes.h"
+#include "utils/memutils.h"
 
 
 typedef struct JoinHashEntry
@@ -598,9 +600,16 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
 						 RelOptInfo *inner_rel, RelOptInfo *parent_joinrel,
 						 JoinType jointype)
 {
-	RelOptInfo *joinrel = makeNode(RelOptInfo);
+	RelOptInfo *joinrel;
 	List	   *join_appinfos;
 
+	MemoryContextCounters mem_start;
+	MemoryContextCounters tlist_mem;
+	MemoryContextCounters jlist_mem;
+
+	MemoryContextFuncStatsStart(CurrentMemoryContext, &mem_start, __FUNCTION__);
+
+	joinrel = makeNode(RelOptInfo);
 	joinrel->reloptkind = RELOPT_OTHER_JOINREL;
 	joinrel->relids = bms_union(outer_rel->relids, inner_rel->relids);
 	joinrel->rows = 0;
@@ -659,16 +668,20 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
 	set_foreign_rel_properties(joinrel, outer_rel, inner_rel);
 
 	/* Build targetlist */
+	MemoryContextFuncStatsStart(CurrentMemoryContext, &tlist_mem, "targetlist");
 	build_joinrel_tlist(root, joinrel, outer_rel);
 	build_joinrel_tlist(root, joinrel, inner_rel);
 	/* Add placeholder variables. */
 	add_placeholders_to_joinrel(root, joinrel, outer_rel, inner_rel);
+	MemoryContextFuncStatsEnd(CurrentMemoryContext, &tlist_mem, "targetlist");
 
 	/* Translate joininfo. */
 	join_appinfos = find_appinfos_by_relids(root, joinrel->relids);
+	MemoryContextFuncStatsStart(CurrentMemoryContext, &jlist_mem, "joininfo");
 	joinrel->joininfo = (List *) adjust_join_appendrel_attrs(root,
 											 (Node *) parent_joinrel->joininfo,
 																join_appinfos);
+	MemoryContextFuncStatsEnd(CurrentMemoryContext, &jlist_mem, "joininfo");
 
 	/*
 	 * Lateral relids referred in child join will be same as that referred in
@@ -700,6 +713,8 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
 
 	pfree(join_appinfos);
 
+	MemoryContextFuncStatsEnd(CurrentMemoryContext, &mem_start, __FUNCTION__);
+
 	return joinrel;
 }
 
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index 5cf388f..bd68a10 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -514,7 +514,7 @@ MemoryContextStatsDetail(MemoryContext context, int max_children)
  * Print this context if print is true, but in any case accumulate counts into
  * *totals (if given).
  */
-static void
+void
 MemoryContextStatsInternal(MemoryContext context, int level,
 						   bool print, int max_children,
 						   MemoryContextCounters *totals)
@@ -1181,3 +1181,29 @@ pnstrdup(const char *in, Size len)
 	out[len] = '\0';
 	return out;
 }
+
+void
+MemoryContextFuncStatsStart(MemoryContext context,
+							MemoryContextCounters *start_counts,
+							const char *label)
+{
+	memset(start_counts, 0, sizeof(*start_counts));
+	MemoryContextStatsInternal(context, 0, false, 100, start_counts);
+}
+
+void
+MemoryContextFuncStatsEnd(MemoryContext context,
+						  MemoryContextCounters *start_counts,
+						  const char *label)
+{
+	MemoryContextCounters end_counts;
+	Size	start_used_space = start_counts->totalspace - start_counts->freespace;
+	Size	end_used_space;
+
+	memset(&end_counts, 0, sizeof(end_counts));
+	MemoryContextStatsInternal(context, 0, false, 100, &end_counts);
+	end_used_space = end_counts.totalspace - end_counts.freespace;
+
+	elog(NOTICE, "%s,%s,%zu,%zu,%ld", label, context->name,
+		 start_used_space, end_used_space, end_used_space - start_used_space);
+}
diff --git a/src/include/utils/memutils.h b/src/include/utils/memutils.h
index e6334a2..6a3ed55 100644
--- a/src/include/utils/memutils.h
+++ b/src/include/utils/memutils.h
@@ -122,6 +122,12 @@ extern MemoryContext MemoryContextCreate(NodeTag tag, Size size,
 					MemoryContextMethods *methods,
 					MemoryContext parent,
 					const char *name);
+extern void MemoryContextFuncStatsStart(MemoryContext context,
+										MemoryContextCounters *start_counts,
+										const char *func_label);
+extern void MemoryContextFuncStatsEnd(MemoryContext context,
+									  MemoryContextCounters *start_counts,
+									  const char *func_label);
 
 
 /*
