blob: 7c38a3c81cc24f53d4dd76912a1ec028e57c9809 [file] [log] [blame]
Brian O'Connor8fdfb062014-01-08 17:47:57 -08001package net.onrc.onos.ofcontroller.flowmanager;
2
Brian O'Connor2daf7a92014-01-14 11:26:35 -08003import java.util.ArrayList;
4import java.util.List;
Brian O'Connor8fdfb062014-01-08 17:47:57 -08005import java.util.Map;
Brian O'Connor2daf7a92014-01-14 11:26:35 -08006import java.util.Map.Entry;
Brian O'Connor8fdfb062014-01-08 17:47:57 -08007import java.util.concurrent.ConcurrentHashMap;
8
9import org.slf4j.Logger;
10import org.slf4j.LoggerFactory;
11
12/**
13 * Class for collecting performance measurements
14 */
15public class PerformanceMonitor {
Brian O'Connor2daf7a92014-01-14 11:26:35 -080016 private final static Map<String, List<Measurement>> map = new ConcurrentHashMap<>();;
Brian O'Connor8fdfb062014-01-08 17:47:57 -080017 private final static Logger log = LoggerFactory.getLogger(PerformanceMonitor.class);
Brian O'Connor2daf7a92014-01-14 11:26:35 -080018 private static long overhead;
19 private static long experimentStart = Long.MAX_VALUE;
20 private final static double normalization = Math.pow(10, 6);
21
Brian O'Connor8fdfb062014-01-08 17:47:57 -080022 /**
23 * Start a performance measurement, identified by a tag
24 *
25 * Note: Only a single measurement can use the same tag at a time.
Brian O'Connor2daf7a92014-01-14 11:26:35 -080026 * ..... not true anymore.
Brian O'Connor8fdfb062014-01-08 17:47:57 -080027 *
28 * @param tag for performance measurement
29 */
Brian O'Connor2daf7a92014-01-14 11:26:35 -080030 public static Measurement start(String tag) {
Brian O'Connor8fdfb062014-01-08 17:47:57 -080031 long start = System.nanoTime();
Brian O'Connor2daf7a92014-01-14 11:26:35 -080032 if(start < experimentStart) {
33 experimentStart = start;
Brian O'Connor8fdfb062014-01-08 17:47:57 -080034 }
Brian O'Connor2daf7a92014-01-14 11:26:35 -080035 List<Measurement> list = map.get(tag);
36 if(list == null) {
37 list = new ArrayList<Measurement>();
38 map.put(tag, list);
39 }
40 Measurement m = new Measurement();
41 list.add(m);
Brian O'Connor8fdfb062014-01-08 17:47:57 -080042 m.start();
43 overhead += System.nanoTime() - start;
Brian O'Connor2daf7a92014-01-14 11:26:35 -080044 return m;
Brian O'Connor8fdfb062014-01-08 17:47:57 -080045 }
46
47 /**
48 * Stop a performance measurement.
49 *
50 * You must have already started a measurement with tag.
51 *
52 * @param tag for performance measurement
53 */
54 public static void stop(String tag) {
55 long time = System.nanoTime();
Brian O'Connor2daf7a92014-01-14 11:26:35 -080056 List<Measurement> list = map.get(tag);
57 if(list == null) {
Brian O'Connor8fdfb062014-01-08 17:47:57 -080058 log.error("Tag {} does not exist", tag);
59 }
Brian O'Connor2daf7a92014-01-14 11:26:35 -080060 else if(list.size() == 1) {
61 list.get(0).stop(time);
62 }
Brian O'Connor8fdfb062014-01-08 17:47:57 -080063 else {
Brian O'Connor2daf7a92014-01-14 11:26:35 -080064 log.error("Tag {} has multiple measurements", tag);
Brian O'Connor8fdfb062014-01-08 17:47:57 -080065 }
66 overhead += System.nanoTime() - time;
67 }
Brian O'Connor2daf7a92014-01-14 11:26:35 -080068
Brian O'Connor8fdfb062014-01-08 17:47:57 -080069 /**
70 * Clear all performance measurements.
71 */
72 public static void clear() {
73 map.clear();
74 overhead = 0;
Brian O'Connor2daf7a92014-01-14 11:26:35 -080075 experimentStart = Long.MAX_VALUE;
Brian O'Connor8fdfb062014-01-08 17:47:57 -080076 }
77
78 /**
79 * Write all performance measurements to the log
80 */
81 public static void report() {
Brian O'Connor2daf7a92014-01-14 11:26:35 -080082 String result = "Performance Results: (avg/start/stop/count)\n";
Brian O'Connor0d9963f2014-01-14 14:44:21 -080083 if(map.size() == 0) {
84 result += "No Measurements";
85 log.error(result);
86 return;
87 }
Brian O'Connor2daf7a92014-01-14 11:26:35 -080088 long experimentEnd = -1;
89 for(Entry<String, List<Measurement>> e : map.entrySet()) {
90 String key = e.getKey();
91 List<Measurement> list = e.getValue();
92 int total = 0, count = 0;
93 long start = Long.MAX_VALUE, stop = -1;
94 for(Measurement m : list) {
95 // Collect overall start and end times
96 if(m.start < start) {
97 start = m.start;
98 }
99 if(m.stop > stop) {
100 stop = m.stop;
101 if(stop > experimentEnd) {
102 experimentEnd = stop;
103 }
104 }
105
106 // Collect statistics for average
107 total += m.elapsed();
108 count++;
109 }
110 double avg = (double) total / count;
111 // Normalize start/stop
112 start -= experimentStart;
113 stop -= experimentStart;
114 result += key + '=' +
115 (avg / normalization) + '/' +
116 (start / normalization) + '/' +
117 (stop / normalization) + '/' +
118 count + '\n';
119 }
120 double overheadMs = overhead / normalization;
121 double experimentElapsed = (experimentEnd - experimentStart) / normalization;
122 result += "TotalTime:" + experimentElapsed + "/Overhead:" + overheadMs;
123 log.error(result);
124// log.error("Performance Results: {} with measurement overhead: {} ms", map, overheadMilli);
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800125 }
Pavlin Radoslavovb5e31782014-01-12 20:11:46 -0800126
127 /**
128 * Write the performance measurement for a tag to the log
129 *
130 * @param tag the tag name.
131 */
132 public static void report(String tag) {
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800133 List<Measurement> list = map.get(tag);
134 if(list == null) {
135 return; //TODO
136 }
137 //TODO: fix this;
138 Measurement m = list.get(0);
Pavlin Radoslavovb5e31782014-01-12 20:11:46 -0800139 if (m != null) {
Brian O'Connor0d9963f2014-01-14 14:44:21 -0800140 log.error("Performance Result: tag = {} start = {} stop = {} elapsed = {}",
Pavlin Radoslavovb5e31782014-01-12 20:11:46 -0800141 tag, m.start, m.stop, m.toString());
142 } else {
Brian O'Connor0d9963f2014-01-14 14:44:21 -0800143 log.error("Performance Result: unknown tag {}", tag);
Pavlin Radoslavovb5e31782014-01-12 20:11:46 -0800144 }
145 }
146
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800147 /**
148 * A single performance measurement
149 */
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800150 public static class Measurement {
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800151 long start;
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800152 long stop = -1;
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800153
154 /**
155 * Start the measurement
156 */
157 public void start() {
158 start = System.nanoTime();
159 }
160
161 /**
162 * Stop the measurement
163 */
164 public void stop() {
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800165 long now = System.nanoTime();
166 stop(now);
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800167 }
168
169 /**
170 * Stop the measurement at a specific time
171 * @param time to stop
172 */
173 public void stop(long time){
174 stop = time;
175 }
176
177 /**
178 * Compute the elapsed time of the measurement in nanoseconds
179 *
180 * @return the measurement time in nanoseconds, or -1 if the measurement is stil running.
181 */
182 public long elapsed() {
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800183 if(stop <= 0) {
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800184 return -1;
185 }
186 else {
187 return stop - start;
188 }
189 }
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800190
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800191 /**
192 * Returns the number of milliseconds for the measurement as a String.
193 */
194 public String toString() {
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800195 double milli = elapsed() / normalization;
196 double startMs = start / normalization;
197 double stopMs = stop / normalization;
198
199 return milli + "ms/" + startMs + '/' + stopMs;
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800200 }
201 }
202
203 public static void main(String args[]){
204 // test the measurement overhead
205 String tag;
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800206 for(int i = 0; i < 2; i++){
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800207 tag = "foo foo foo";
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800208 Measurement m;
209 m = start(tag); System.out.println(tag); m.stop();
210 m = start(tag); System.out.println(tag); m.stop();
211 m = start(tag); System.out.println(tag); m.stop();
212 m = start(tag); System.out.println(tag); m.stop();
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800213 tag = "bar";
214 start(tag); stop(tag);
215 tag = "baz";
216 start(tag); stop(tag);
217 report();
218 clear();
219 }
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800220// for(int i = 0; i < 100; i++){
221// tag = "a";
222// start(tag); stop(tag);
223// tag = "b";
224// start(tag); stop(tag);
225// tag = "c";
226// start(tag); stop(tag);
227// report();
228// clear();
229// }
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800230 }
231}