diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/Profiler.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/Profiler.java
new file mode 100644
index 00000000000..73144c884e5
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/Profiler.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Google, Inc and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Sergey Prigogin (Google) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.core.parser.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Manual profiler for focused thread-specific profiling.
+ *
+ * Usage example:
+ *
+ * Profiler.activate();
+ * // Code to profile
+ * if (starsAlign) {
+ * Profiler.printStats();
+ * }
+ * Profiler.deactivate();
+ *
+ * void someMethod() {
+ * try {
+ * Profiler.startTimer("MyClass.someMethod");
+ * // Code to get timing for.
+ * } finally {
+ * Profiler.stopTimer("MyClass.someMethod");
+ * }
+ * }
+ *
+ * void someOtherMethod() {
+ * ...
+ * Profiler.incrementCounter("Interesting thing happened");
+ * ...
+ * }
+ *
+ */
+public class Profiler {
+ private static class Timer {
+ long elapsedTime; // In nanoseconds
+ long counter;
+ long startTime; // Time in nanoseconds when the timer was started.
+ int recursionDepth;
+
+ final long getElapsedTime() {
+ return elapsedTime;
+ }
+
+ final long getCounter() {
+ return counter;
+ }
+
+ final void recordEntry() {
+ if (recursionDepth++ == 0) {
+ startTime = System.nanoTime();
+ }
+ }
+
+ final void recordExit() {
+ if (--recursionDepth == 0) {
+ elapsedTime += System.nanoTime() - startTime;
+ counter++;
+ }
+ }
+ }
+
+ private Map timers;
+ private Map counters;
+
+ private Profiler() {
+ timers = new HashMap();
+ counters = new HashMap();
+ }
+
+ private static ThreadLocal threadProfiler = new ThreadLocal();
+
+ /**
+ *
+ * @param name
+ */
+ public static void startTimer(String name) {
+ Profiler profiler = threadProfiler.get();
+ if (profiler != null) {
+ Timer timer = profiler.timers.get(name);
+ if (timer == null) {
+ timer = new Timer();
+ profiler.timers.put(name, timer);
+ }
+ timer.recordEntry();
+ }
+ }
+
+ public static void stopTimer(String name) {
+ Profiler profiler = threadProfiler.get();
+ if (profiler != null) {
+ Timer timer = profiler.timers.get(name);
+ timer.recordExit();
+ }
+ }
+
+ public static void incrementCounter(String name) {
+ Profiler profiler = threadProfiler.get();
+ if (profiler != null) {
+ Integer n = profiler.counters.get(name);
+ if (n == null) {
+ n = 1;
+ } else {
+ n = n.intValue() + 1;
+ }
+ profiler.counters.put(name, n);
+ }
+ }
+
+ public static void activate() {
+ threadProfiler.set(new Profiler());
+ }
+
+ public static void deactivate() {
+ threadProfiler.set(null);
+ }
+
+ public static void printStats() {
+ Profiler profiler = threadProfiler.get();
+ if (profiler != null) {
+ List> list =
+ new ArrayList>(profiler.timers.entrySet());
+ Comparator> c = new Comparator>() {
+ public int compare(Entry o1, Entry o2) {
+ long diff = o2.getValue().getElapsedTime() - o1.getValue().getElapsedTime();
+ return diff < 0 ? -1 : diff > 0 ? 1 : 0;
+ }
+ };
+ Collections.sort(list, c);
+ System.out.println("==="); //$NON-NLS-1$
+ for (Entry item : list) {
+ System.out.println("===\t" + ((item.getValue().getElapsedTime() + 500000) / 1000000) + //$NON-NLS-1$
+ "\t"+ item.getValue().getCounter() + "\t" + item.getKey()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ if (!profiler.counters.isEmpty()) {
+ List> keyList =
+ new ArrayList>(profiler.counters.entrySet());
+ Comparator> c2 = new Comparator>() {
+ public int compare(Entry o1, Entry o2) {
+ return o2.getValue().intValue() - o1.getValue().intValue();
+ }
+ };
+ Collections.sort(keyList, c2);
+ System.out.println("==="); //$NON-NLS-1$
+ System.out.println("===\t" + profiler.counters.size() + " counters"); //$NON-NLS-1$ //$NON-NLS-2$
+ for (Entry item : keyList) {
+ System.out.println("===\t" + item.getValue().intValue() + "\t" + item.getKey()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ }
+ }
+}