Index: src/Common/Stats.h
===================================================================
--- src/Common/Stats.h	(revision 675716ec02a392a1cd187946766c1829aeb097e5)
+++ src/Common/Stats.h	(revision 1cb7fab24a9d8ae701d8295e3857478969f5fd45)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Heap.h --
+// Stats.h --
 //
 // Author           : Thierry Delisle
@@ -18,2 +18,8 @@
 #include "Common/Stats/Counter.h"
 #include "Common/Stats/Heap.h"
+#include "Common/Stats/Time.h"
+
+namespace Stats {
+	void parse_params(const char * const params);
+	void print();
+}
Index: src/Common/Stats/Base.h
===================================================================
--- src/Common/Stats/Base.h	(revision 675716ec02a392a1cd187946766c1829aeb097e5)
+++ src/Common/Stats/Base.h	(revision 1cb7fab24a9d8ae701d8295e3857478969f5fd45)
@@ -16,25 +16,24 @@
 #pragma once
 
-#include <string>
-
 namespace Stats {
 	namespace Base {
+		class TreeImpl;
+
+		struct TreeTop {
+			TreeImpl * head = nullptr;
+			TreeImpl * tail = nullptr;
+
+			inline void append(TreeImpl * node);
+		};
+
+		template<typename func_t>
+		void ForAll(TreeTop & range, size_t level, func_t func, bool destroy = false);
+
 		class TreeImpl {
 		public:
-			struct Top {
-				TreeImpl * head = nullptr;
-				TreeImpl * tail = nullptr;
-
-				void append(TreeImpl * node) {
-					if(!head) { head = node; }
-					else      { tail->next = node;}
-					tail = node;
-				}
-			};
-
 			virtual void print(std::ostream &) = 0;
 
-			const std::string name;
-			TreeImpl(const std::string & name) : name(name) {}
+			const char * const name;
+			TreeImpl(const char * const name) : name(name) {}
 
 		protected:
@@ -42,12 +41,20 @@
 
 			TreeImpl * next = nullptr;
-			Top children;
+			TreeTop children;
+
+			friend struct TreeTop;
 
 			template<typename func_t>
-			friend void ForAll(TreeImpl::Top & range, size_t level, func_t func, bool destroy = false);
+			friend void ForAll(TreeTop & range, size_t level, func_t func, bool destroy);
 		};
 
+		void TreeTop::append(TreeImpl * node) {
+			if(!head) { head = node; }
+			else      { tail->next = node;}
+			tail = node;
+		}
+
 		template<typename func_t>
-		inline void ForAll(TreeImpl::Top & range, size_t level, func_t func, bool destroy) {
+		inline void ForAll(TreeTop & range, size_t level, func_t func, bool destroy) {
 			auto it = range.head;
 			while(it) {
@@ -60,12 +67,12 @@
 		}
 
-		template<TreeImpl::Top & top>
+		template<TreeTop & top>
 		class Tree : public TreeImpl {
 		public:
-			Tree(const std::string & name) : TreeImpl{name} {
+			Tree(const char * const name) : TreeImpl{name} {
 				top.append(this);
 			}
 
-			Tree(const std::string & name, Tree * parent) : TreeImpl{name} {
+			Tree(const char * const name, Tree * parent) : TreeImpl{name} {
 				parent->children.append(this);
 			}
Index: src/Common/Stats/Counter.cc
===================================================================
--- src/Common/Stats/Counter.cc	(revision 675716ec02a392a1cd187946766c1829aeb097e5)
+++ src/Common/Stats/Counter.cc	(revision 1cb7fab24a9d8ae701d8295e3857478969f5fd45)
@@ -27,11 +27,11 @@
 			size_t nc = 0;
 			Base::ForAll(top, 0, [&](Base::TreeImpl * node, size_t level) {
-				nc = std::max(nc, (4 * level) + node->name.size());
+				nc = std::max(nc, (4 * level) + std::strlen(node->name));
 			});
 
-			const std::string & title = "Counter Statistic";
+			const char * const title = "Counter Statistic";
 			size_t nct = nc + 14;
 			std::cerr << std::string(nct, '=') << std::endl;
-			std::cerr << std::string((nct - title.size()) / 2, ' ');
+			std::cerr << std::string((nct - std::strlen(title)) / 2, ' ');
 			std::cerr << title << std::endl;
 			std::cerr << std::string(nct, '-') << std::endl;
@@ -41,5 +41,5 @@
 				std::cerr << std::string(level * 4, ' ');
 				std::cerr << node->name;
-				std::cerr << std::string(nc - ((level * 4) + node->name.size()), ' ');
+				std::cerr << std::string(nc - ((level * 4) + std::strlen(node->name)), ' ');
 				std::cerr << " | ";
 				std::cerr << std::setw(9);
@@ -52,5 +52,7 @@
 		}
 
-		Base::TreeImpl::Top top;
+		Base::TreeTop top;
+
+		extern bool enabled;
 	}
 }
Index: src/Common/Stats/Counter.h
===================================================================
--- src/Common/Stats/Counter.h	(revision 675716ec02a392a1cd187946766c1829aeb097e5)
+++ src/Common/Stats/Counter.h	(revision 1cb7fab24a9d8ae701d8295e3857478969f5fd45)
@@ -18,76 +18,127 @@
 #include <cstdint>
 #include <iostream>
-#include <string>
 
 #include "Common/Stats/Base.h"
 
+#if defined( NO_STATISTICS )
+	#define NO_COUNTER_STATISTICS
+#endif
+
 namespace Stats {
 	namespace Counters {
-		void print();
+# 		if defined(NO_COUNTERS_STATISTICS)
 
-		extern Base::TreeImpl::Top top;
+			static inline void print() {}
 
-		class CounterGroup : public Base::Tree<top> {
-		public:
-			CounterGroup(const std::string & name ) : Base::Tree<top>(name) {}
-			CounterGroup(const std::string & name, Base::Tree<top> * parent) : Base::Tree<top>(name, parent) {}
+			class CounterGroup {
+			public:
+			};
 
-			virtual void print(std::ostream & os) override { os << ""; }
-		protected:
-			virtual ~CounterGroup() = default;
-		};
+			class SimpleCounter {
+			public:
+				inline void operator++(int) {}
+				inline void operator+=(size_t) {}
+			};
 
-		class SimpleCounter : public Base::Tree<top> {
-		public:
-			SimpleCounter(const std::string & name ) : Base::Tree<top>(name) {}
-			SimpleCounter(const std::string & name, Base::Tree<top> * parent) : Base::Tree<top>(name, parent) {}
+			template<typename T>
+			class AverageCounter {
+			public:
+				inline void push(T value) {}
+			};
 
-			virtual void print(std::ostream & os) override { os << count; }
+			template<typename T>
+			class MaxCounter {
+			public:
+				inline void push(T value) {}
+			};
 
-			inline void operator++(int)          { count++;        }
-			inline void operator+=(size_t value) { count += value; }
-		protected:
-			virtual ~SimpleCounter() = default;
-
-		private:
-			size_t count = 0;
-		};
-
-		template<typename T>
-		class AverageCounter : public Base::Tree<top> {
-		public:
-			AverageCounter(const std::string & name ) : Base::Tree<top>(name), sum{} {}
-			AverageCounter(const std::string & name, Base::Tree<top> * parent) : Base::Tree<top>(name, parent), sum{} {}
-
-			virtual void print(std::ostream & os) { os << sum / count; }
-
-			inline void push(T value) {
-				sum += value;
-				count++;
+			template<typename counter_t>
+			counter_t * build(const char * const name) {
+				return nullptr;
 			}
 
-		protected:
-			virtual ~AverageCounter() = default;
+			template<typename counter_t>
+			counter_t * build(const char * const name, Base::Tree<top> * parent) {
+					return nullptr;
+			}
+#		else
+			extern bool enabled;
 
-		private:
-			T sum;
-			size_t count = 1;
-		};
+			extern Base::TreeTop top;
 
-		template<typename T>
-		class MaxCounter : public Base::Tree<top> {
-		public:
-			MaxCounter(const std::string & name ) : Base::Tree<top>(name), max{} {}
-			MaxCounter(const std::string & name, Base::Tree<top> * parent) : Base::Tree<top>(name, parent), max{} {}
+			class CounterGroup : public Base::Tree<top> {
+			public:
+				CounterGroup(const char * const name ) : Base::Tree<top>(name) {}
+				CounterGroup(const char * const name, Base::Tree<top> * parent) : Base::Tree<top>(name, parent) {}
 
-			virtual void print(std::ostream & os) { os << max; }
+				virtual void print(std::ostream & os) override { os << ""; }
+			protected:
+				virtual ~CounterGroup() = default;
+			};
 
-			inline void push(T value) { max = std::max(max, value); }
-		protected:
-			virtual ~MaxCounter() = default;
+			class SimpleCounter : public Base::Tree<top> {
+			public:
+				SimpleCounter(const char * const name ) : Base::Tree<top>(name) {}
+				SimpleCounter(const char * const name, Base::Tree<top> * parent) : Base::Tree<top>(name, parent) {}
 
-		private:
-			T max;
-		};
+				virtual void print(std::ostream & os) override { os << count; }
+
+				inline void operator++(int)          { if(!enabled) return; count++;        }
+				inline void operator+=(size_t value) { if(!enabled) return; count += value; }
+
+			protected:
+				virtual ~SimpleCounter() = default;
+
+			private:
+				size_t count = 0;
+			};
+
+			template<typename T>
+			class AverageCounter : public Base::Tree<top> {
+			public:
+				AverageCounter(const char * const name ) : Base::Tree<top>(name), sum{} {}
+				AverageCounter(const char * const name, Base::Tree<top> * parent) : Base::Tree<top>(name, parent), sum{} {}
+
+				virtual void print(std::ostream & os) { os << sum / count; }
+
+				inline void push(T value) { if(!enabled) return; sum += value; count++; }
+
+			protected:
+				virtual ~AverageCounter() = default;
+
+			private:
+				T sum;
+				size_t count = 1;
+			};
+
+			template<typename T>
+			class MaxCounter : public Base::Tree<top> {
+			public:
+				MaxCounter(const char * const name ) : Base::Tree<top>(name), max{} {}
+				MaxCounter(const char * const name, Base::Tree<top> * parent) : Base::Tree<top>(name, parent), max{} {}
+
+				virtual void print(std::ostream & os) { os << max; }
+
+				inline void push(T value) { if(!enabled) return; max = std::max(max, value); }
+
+			protected:
+				virtual ~MaxCounter() = default;
+
+			private:
+				T max;
+			};
+
+			template<typename counter_t>
+			counter_t * build(const char * const name) {
+				if(!enabled) return nullptr;
+				return new counter_t(name);
+			}
+
+			template<typename counter_t>
+			counter_t * build(const char * const name, Base::Tree<top> * parent) {
+				if(!enabled) return nullptr;
+				return new counter_t(name, parent);
+			}
+#		endif
 	}
 }
Index: src/Common/Stats/Heap.cc
===================================================================
--- src/Common/Stats/Heap.cc	(revision 675716ec02a392a1cd187946766c1829aeb097e5)
+++ src/Common/Stats/Heap.cc	(revision 1cb7fab24a9d8ae701d8295e3857478969f5fd45)
@@ -21,4 +21,8 @@
 #include <iostream>
 
+#if defined( NO_STATISTICS )
+	#define NO_HEAP_STATISTICS
+#endif
+
 namespace Stats {
 	namespace Heap {
@@ -28,4 +32,6 @@
 		void print() {}
 #else
+		extern bool enabled;
+
 		struct StatBlock {
 			const char * name  = nullptr;	///< Name of this pass
@@ -77,4 +83,6 @@
 
 		void print() {
+			if(!enabled) return;
+
 			size_t nc = 0;
 			size_t total_mallocs = 0;
@@ -166,5 +174,5 @@
 			void * malloc( size_t size ) {
 				static auto __malloc = reinterpret_cast<void * (*)(size_t)>(interpose_symbol( "malloc", nullptr ));
-				if( passes_cnt > 0 ) {
+				if( enabled && passes_cnt > 0 ) {
 					passes[passes_cnt - 1].mallocs++;
 					passes[passes_cnt - 1].n_allocs++;
@@ -177,5 +185,5 @@
 			void free( void * ptr ) {
 				static auto __free = reinterpret_cast<void   (*)(void *)>(interpose_symbol( "free", nullptr ));
-				if( passes_cnt > 0 ) {
+				if( enabled && passes_cnt > 0 ) {
 					passes[passes_cnt - 1].frees++;
 					passes[passes_cnt - 1].n_allocs--;
@@ -186,5 +194,5 @@
 			void * calloc( size_t nelem, size_t size ) {
 				static auto __calloc = reinterpret_cast<void * (*)(size_t, size_t)>(interpose_symbol( "calloc", nullptr ));
-				if( passes_cnt > 0 ) {
+				if( enabled && passes_cnt > 0 ) {
 					passes[passes_cnt - 1].mallocs++;
 					passes[passes_cnt - 1].n_allocs++;
@@ -198,5 +206,5 @@
 				static auto __realloc = reinterpret_cast<void * (*)(void *, size_t)>(interpose_symbol( "realloc", nullptr ));
 				void * s = __realloc( ptr, size );
-				if ( s != ptr && passes_cnt > 0 ) {			// did realloc get new storage ?
+				if ( enabled && s != ptr && passes_cnt > 0 ) {			// did realloc get new storage ?
 					passes[passes_cnt - 1].mallocs++;
 					passes[passes_cnt - 1].frees++;
Index: src/Common/Stats/Stats.cc
===================================================================
--- src/Common/Stats/Stats.cc	(revision 1cb7fab24a9d8ae701d8295e3857478969f5fd45)
+++ src/Common/Stats/Stats.cc	(revision 1cb7fab24a9d8ae701d8295e3857478969f5fd45)
@@ -0,0 +1,86 @@
+//
+// 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.
+//
+// Stats.cc --
+//
+// Author           : Thierry Delisle
+// Created On       : Fri Mar 01 15:45:08 2019
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#include <iostream>
+#include <sstream>
+#include <string>
+
+
+namespace Stats {
+	namespace Counters {
+		bool enabled = false;
+		void print();
+	}
+
+	namespace Heap {
+		bool enabled = false;
+		void print();
+	}
+
+	namespace Time {
+		bool enabled = false;
+		void print() {}
+	}
+
+	struct {
+		const char * const opt;
+		bool & enabled;
+	}
+	statistics[] = {
+		{ "counters", Counters::enabled },
+		{ "heap"    , Heap::enabled },
+		{ "time"    , Time::enabled },
+	};
+
+	void set_param(std::string & param) {
+		if(param == "all") {
+			for(auto & stat : statistics) {
+				stat.enabled = true;
+			}
+			return;
+		}
+
+		if(param == "none") {
+			for(auto & stat : statistics) {
+				stat.enabled = false;
+			}
+			return;
+		}
+
+		for(auto & stat : statistics) {
+			if(stat.opt == param) {
+				stat.enabled = true;
+				return;
+			}
+		}
+
+		std::cerr << "Ignoring unknown statistic " << param << std::endl;
+	}
+
+	void parse_params(const char * const params) {
+		std::stringstream ss(params);
+		while(ss.good()) {
+			std::string substr;
+			getline( ss, substr, ',' );
+			set_param(substr);
+		}
+	}
+
+	void print() {
+		Counters::print();
+		Heap::print();
+		Time::print();
+	}
+}
Index: src/Common/Stats/Time.h
===================================================================
--- src/Common/Stats/Time.h	(revision 1cb7fab24a9d8ae701d8295e3857478969f5fd45)
+++ src/Common/Stats/Time.h	(revision 1cb7fab24a9d8ae701d8295e3857478969f5fd45)
@@ -0,0 +1,38 @@
+//
+// 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.
+//
+// Time.h --
+//
+// Author           : Thierry Delisle
+// Created On       : Fri Mar 01 15:14:11 2019
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#pragma once
+
+#include "Common/Stats/Base.h"
+
+namespace Stats {
+	namespace Time {
+		void StartBlock(const char * const name);
+		void StopBlock();
+
+		void print();
+
+		struct BlockGuard {
+			BlockGuard(const char * const name ) { StartBlock(name); }
+			~BlockGuard() { StopBlock(); }
+		};
+
+		template<typename func_t>
+		void TimeBLock(const char * name, func_t func) {
+			BlockGuard guard(name);
+			func();
+		}
+	}
+}
Index: src/Common/module.mk
===================================================================
--- src/Common/module.mk	(revision 675716ec02a392a1cd187946766c1829aeb097e5)
+++ src/Common/module.mk	(revision 1cb7fab24a9d8ae701d8295e3857478969f5fd45)
@@ -20,6 +20,7 @@
       Common/PassVisitor.cc \
       Common/SemanticError.cc \
+      Common/Stats/Counter.cc \
       Common/Stats/Heap.cc \
-      Common/Stats/Counter.cc \
+      Common/Stats/Stats.cc \
       Common/UniqueName.cc
 
