blob: fa754601f5d9f3f23fde9fa3714bb6cfdb5d046e [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);
brian6df88232014-01-14 17:05:07 -080057 if(list == null || list.size() == 0) {
Brian O'Connor8fdfb062014-01-08 17:47:57 -080058 log.error("Tag {} does not exist", tag);
59 }
brian6df88232014-01-14 17:05:07 -080060 list.get(0).stop(time);
61 if(list.size() > 1) {
Brian O'Connor2daf7a92014-01-14 11:26:35 -080062 log.error("Tag {} has multiple measurements", tag);
Brian O'Connor8fdfb062014-01-08 17:47:57 -080063 }
64 overhead += System.nanoTime() - time;
65 }
Brian O'Connor2daf7a92014-01-14 11:26:35 -080066
Brian O'Connor8fdfb062014-01-08 17:47:57 -080067 /**
68 * Clear all performance measurements.
69 */
70 public static void clear() {
71 map.clear();
72 overhead = 0;
Brian O'Connor2daf7a92014-01-14 11:26:35 -080073 experimentStart = Long.MAX_VALUE;
Brian O'Connor8fdfb062014-01-08 17:47:57 -080074 }
75
76 /**
77 * Write all performance measurements to the log
78 */
79 public static void report() {
Brian O'Connor2daf7a92014-01-14 11:26:35 -080080 String result = "Performance Results: (avg/start/stop/count)\n";
Brian O'Connor0d9963f2014-01-14 14:44:21 -080081 if(map.size() == 0) {
82 result += "No Measurements";
83 log.error(result);
84 return;
85 }
Brian O'Connor2daf7a92014-01-14 11:26:35 -080086 long experimentEnd = -1;
87 for(Entry<String, List<Measurement>> e : map.entrySet()) {
88 String key = e.getKey();
89 List<Measurement> list = e.getValue();
90 int total = 0, count = 0;
91 long start = Long.MAX_VALUE, stop = -1;
92 for(Measurement m : list) {
brian6df88232014-01-14 17:05:07 -080093 if(m.stop < 0) {
94 continue; // measurement has not been stopped
95 }
Brian O'Connor2daf7a92014-01-14 11:26:35 -080096 // Collect overall start and end times
97 if(m.start < start) {
98 start = m.start;
99 }
100 if(m.stop > stop) {
101 stop = m.stop;
102 if(stop > experimentEnd) {
103 experimentEnd = stop;
104 }
brian6df88232014-01-14 17:05:07 -0800105 }
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800106 // 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() {
brian6df88232014-01-14 17:05:07 -0800158 if(start <= 0) {
159 start = System.nanoTime();
160 }
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800161 }
162
163 /**
164 * Stop the measurement
165 */
166 public void stop() {
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800167 long now = System.nanoTime();
168 stop(now);
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800169 }
170
171 /**
172 * Stop the measurement at a specific time
173 * @param time to stop
174 */
175 public void stop(long time){
brian6df88232014-01-14 17:05:07 -0800176 if(stop <= 0) {
177 stop = time;
178 }
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800179 }
180
181 /**
182 * Compute the elapsed time of the measurement in nanoseconds
183 *
184 * @return the measurement time in nanoseconds, or -1 if the measurement is stil running.
185 */
186 public long elapsed() {
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800187 if(stop <= 0) {
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800188 return -1;
189 }
190 else {
191 return stop - start;
192 }
193 }
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800194
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800195 /**
196 * Returns the number of milliseconds for the measurement as a String.
197 */
198 public String toString() {
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800199 double milli = elapsed() / normalization;
200 double startMs = start / normalization;
201 double stopMs = stop / normalization;
202
203 return milli + "ms/" + startMs + '/' + stopMs;
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800204 }
205 }
206
207 public static void main(String args[]){
208 // test the measurement overhead
209 String tag;
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800210 for(int i = 0; i < 2; i++){
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800211 tag = "foo foo foo";
Brian O'Connor2daf7a92014-01-14 11:26:35 -0800212 Measurement m;
213 m = start(tag); System.out.println(tag); m.stop();
214 m = start(tag); System.out.println(tag); m.stop();
215 m = start(tag); System.out.println(tag); m.stop();
216 m = start(tag); System.out.println(tag); m.stop();
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800217 tag = "bar";
218 start(tag); stop(tag);
219 tag = "baz";
220 start(tag); stop(tag);
221 report();
222 clear();
223 }
brian6df88232014-01-14 17:05:07 -0800224 for(int i = 0; i < 100; i++){
225 tag = "a";
226 start(tag); stop(tag);
227 start(tag); stop(tag);
228
229 start(tag); stop(tag);
230 start(tag); stop(tag);
231 start(tag); stop(tag);
232 start(tag); stop(tag);
233 start(tag); stop(tag);
234 start(tag); stop(tag);
235
236 tag = "b";
237 start(tag); stop(tag);
238 tag = "c";
239 start(tag); stop(tag);
240 report();
241 clear();
242 }
Brian O'Connor8fdfb062014-01-08 17:47:57 -0800243 }
244}