Index: src/Common/Stats.h
===================================================================
--- src/Common/Stats.h	(revision 7abee383f06a7fe5690784e7676edcdf68ff7660)
+++ src/Common/Stats.h	(revision 8f74a6a90dfafe7f15a3b81e2fb32de2141df58c)
@@ -16,3 +16,4 @@
 #pragma once
 
+#include "Common/Stats/Counter.h"
 #include "Common/Stats/Heap.h"
Index: src/Common/Stats/Counter.cc
===================================================================
--- src/Common/Stats/Counter.cc	(revision 8f74a6a90dfafe7f15a3b81e2fb32de2141df58c)
+++ src/Common/Stats/Counter.cc	(revision 8f74a6a90dfafe7f15a3b81e2fb32de2141df58c)
@@ -0,0 +1,67 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Heap.h --
+//
+// Author           : Thierry Delisle
+// Created On       : Thu Feb 28 13::27:10 2019
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#include "Counter.h"
+
+#include <algorithm>
+#include <cstring>
+#include <iomanip>
+
+namespace Stats {
+	namespace Counters {
+
+		template<typename T>
+		void ForAllCounters(BaseCounter::list_t & range, size_t level, T func) {
+			auto it = range.head;
+			while(it) {
+				auto next = it->next;
+				func(it, level);
+				ForAllCounters(it->children, level + 1, func);
+				it = next;
+			}
+		}
+
+		void print() {
+			size_t nc = 0;
+			ForAllCounters(BaseCounter::top, 0, [&](BaseCounter * node, size_t level) {
+				nc = std::max(nc, (4 * level) + std::strlen(node->name));
+			});
+
+			const char * const title = "Counter Statistic";
+			size_t nct = nc + 14;
+			std::cerr << std::string(nct, '=') << std::endl;
+			std::cerr << std::string((nct - std::strlen(title)) / 2, ' ');
+			std::cerr << title << std::endl;
+			std::cerr << std::string(nct, '-') << std::endl;
+
+
+			ForAllCounters(BaseCounter::top, 0, [&](BaseCounter * node, size_t level) {
+				std::cerr << std::string(level * 4, ' ');
+				std::cerr << node->name;
+				std::cerr << std::string(nc - ((level * 4) + std::strlen(node->name)), ' ');
+				std::cerr << " | ";
+				std::cerr << std::setw(9);
+				node->print(std::cerr);
+				std::cerr << " |";
+				std::cerr << '\n';
+				delete node;
+			});
+
+			std::cerr << std::string(nct, '-') << std::endl;
+		}
+
+		BaseCounter::list_t BaseCounter::top;
+	}
+}
Index: src/Common/Stats/Counter.h
===================================================================
--- src/Common/Stats/Counter.h	(revision 8f74a6a90dfafe7f15a3b81e2fb32de2141df58c)
+++ src/Common/Stats/Counter.h	(revision 8f74a6a90dfafe7f15a3b81e2fb32de2141df58c)
@@ -0,0 +1,128 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Heap.h --
+//
+// Author           : Thierry Delisle
+// Created On       : Thu Feb 28 12::05:10 2019
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#pragma once
+
+#include <cstdint>
+#include <iostream>
+
+namespace Stats {
+	namespace Counters {
+		void print();
+
+		class BaseCounter {
+		public:
+			BaseCounter(const char * const name) : name(name) {
+				top.append(this);
+			}
+
+			BaseCounter(const char * const name, BaseCounter * parent) : name(name) {
+				parent->children.append(this);
+			}
+		protected:
+			virtual ~BaseCounter() = default;
+
+			struct list_t {
+				BaseCounter * head = nullptr;
+				BaseCounter * tail = nullptr;
+
+				void append(BaseCounter * node) {
+					if(!head) { head = node; }
+					else      { tail->next = node;}
+					tail = node;
+				}
+			};
+
+		private:
+			virtual void print(std::ostream &) = 0;
+			template<typename T>
+			friend void ForAllCounters(BaseCounter::list_t &, size_t, T );
+			friend void print();
+
+		private:
+			const char * const name;
+
+			BaseCounter * next = nullptr;
+			list_t children;
+
+			static list_t top;
+		};
+
+		class CounterGroup : public BaseCounter {
+		public:
+			CounterGroup(const char * const name ) : BaseCounter(name) {}
+			CounterGroup(const char * const name, BaseCounter * parent) : BaseCounter(name, parent) {}
+
+		protected:
+			virtual ~CounterGroup() = default;
+
+		private:
+			virtual void print(std::ostream & os) {
+				os << "";
+			}
+			template<typename T>
+			friend void ForAllCounters(BaseCounter::list_t &, size_t, T );
+			friend void print();
+		};
+
+		class SimpleCounter : public BaseCounter {
+		public:
+			SimpleCounter(const char * const name ) : BaseCounter(name) {}
+			SimpleCounter(const char * const name, BaseCounter * parent) : BaseCounter(name, parent) {}
+
+			inline void operator++(int)          { count++;        }
+			inline void operator+=(size_t value) { count += value; }
+		protected:
+			virtual ~SimpleCounter() = default;
+
+		private:
+			virtual void print(std::ostream & os) {
+				os << count;
+			}
+			template<typename T>
+			friend void ForAllCounters(BaseCounter::list_t &, size_t, T );
+			friend void print();
+
+			size_t count = 0;
+
+		};
+
+		template<typename T>
+		class AverageCounter : public BaseCounter {
+		public:
+			AverageCounter(const char * const name ) : BaseCounter(name), sum{} {}
+			AverageCounter(const char * const name, BaseCounter * parent) : BaseCounter(name, parent), sum{} {}
+
+			inline void push(T value) {
+				sum += value;
+				count++;
+			}
+
+		protected:
+			virtual ~AverageCounter() = default;
+
+		private:
+			virtual void print(std::ostream & os) {
+				os << sum / count;
+			}
+			template<typename F>
+			friend void ForAllCounters(BaseCounter::list_t &, size_t, F );
+			friend void print();
+
+			T sum;
+			size_t count = 1;
+		};
+	}
+}
Index: src/Common/Stats/Heap.cc
===================================================================
--- src/Common/Stats/Heap.cc	(revision 7abee383f06a7fe5690784e7676edcdf68ff7660)
+++ src/Common/Stats/Heap.cc	(revision 8f74a6a90dfafe7f15a3b81e2fb32de2141df58c)
@@ -21,12 +21,10 @@
 #include <iostream>
 
-//#define WITH_HEAP_STATISTICS
-
 namespace Stats {
 	namespace Heap {
-#if !defined( WITH_HEAP_STATISTICS )
+#if defined( NO_HEAP_STATISTICS )
 		void newPass( const char * const ) {}
 
-		void printStats() {}
+		void print() {}
 #else
 		struct StatBlock {
@@ -78,5 +76,5 @@
 		}
 
-		void printStats() {
+		void print() {
 			size_t nc = 0;
 			size_t total_mallocs = 0;
Index: src/Common/Stats/Heap.h
===================================================================
--- src/Common/Stats/Heap.h	(revision 7abee383f06a7fe5690784e7676edcdf68ff7660)
+++ src/Common/Stats/Heap.h	(revision 8f74a6a90dfafe7f15a3b81e2fb32de2141df58c)
@@ -19,5 +19,5 @@
 	namespace Heap {
 		void newPass( const char * const name );
-		void printStats();
+		void print();
 	}
 }
Index: src/Common/module.mk
===================================================================
--- src/Common/module.mk	(revision 7abee383f06a7fe5690784e7676edcdf68ff7660)
+++ src/Common/module.mk	(revision 8f74a6a90dfafe7f15a3b81e2fb32de2141df58c)
@@ -18,4 +18,5 @@
       Common/Assert.cc \
       Common/Stats/Heap.cc \
+      Common/Stats/Counter.cc \
       Common/Eval.cc \
       Common/SemanticError.cc \
Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision 7abee383f06a7fe5690784e7676edcdf68ff7660)
+++ src/Makefile.in	(revision 8f74a6a90dfafe7f15a3b81e2fb32de2141df58c)
@@ -166,6 +166,6 @@
 	CodeGen/OperatorTable.$(OBJEXT)
 am__objects_2 = Common/Assert.$(OBJEXT) Common/Stats/Heap.$(OBJEXT) \
-	Common/Eval.$(OBJEXT) Common/SemanticError.$(OBJEXT) \
-	Common/UniqueName.$(OBJEXT)
+	Common/Stats/Counter.$(OBJEXT) Common/Eval.$(OBJEXT) \
+	Common/SemanticError.$(OBJEXT) Common/UniqueName.$(OBJEXT)
 am__objects_3 = ControlStruct/ForExprMutator.$(OBJEXT) \
 	ControlStruct/LabelFixer.$(OBJEXT) \
@@ -561,4 +561,5 @@
       Common/Assert.cc \
       Common/Stats/Heap.cc \
+      Common/Stats/Counter.cc \
       Common/Eval.cc \
       Common/SemanticError.cc \
@@ -727,4 +728,6 @@
 	@: > Common/Stats/$(DEPDIR)/$(am__dirstamp)
 Common/Stats/Heap.$(OBJEXT): Common/Stats/$(am__dirstamp) \
+	Common/Stats/$(DEPDIR)/$(am__dirstamp)
+Common/Stats/Counter.$(OBJEXT): Common/Stats/$(am__dirstamp) \
 	Common/Stats/$(DEPDIR)/$(am__dirstamp)
 Common/Eval.$(OBJEXT): Common/$(am__dirstamp) \
@@ -1114,4 +1117,5 @@
 @AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/SemanticError.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@Common/$(DEPDIR)/UniqueName.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@Common/Stats/$(DEPDIR)/Counter.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@Common/Stats/$(DEPDIR)/Heap.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@Concurrency/$(DEPDIR)/Keywords.Po@am__quote@
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 7abee383f06a7fe5690784e7676edcdf68ff7660)
+++ src/main.cc	(revision 8f74a6a90dfafe7f15a3b81e2fb32de2141df58c)
@@ -377,5 +377,9 @@
 
 	deleteAll( translationUnit );
-	if(!libcfap && !treep) Stats::Heap::printStats();
+	if(!libcfap && !treep) {
+		Stats::Counters::print();
+		Stats::Heap::print();
+	}
+
 	return 0;
 } // main
