From 388ee55b6e5d9c1506ca8e789d85e56834b5f67a Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Sat, 31 Oct 2009 22:39:04 +0000 Subject: [PATCH] Manual profiler for focused thread-specific profiling. --- .../internal/core/parser/util/Profiler.java | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/Profiler.java 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$ + } + } + } + } +}