Add backend support for collecting the time it takes to
install each Flow.
The new REST call is "wm/flow/measurement-get-per-flow-install-time/json"
The result is returned in a multi-line string with the following format
per line:
ThreadAndTimePerFlow <ThreadId> <TotalThreads> <Time(ns)>
diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
index 1020eab..8aec20f 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
@@ -99,6 +99,7 @@
private long measurementStartTimeProcessingPaths = 0;
private long measurementEndTimeProcessingPaths = 0;
Map<Long, ?> measurementShortestPathTopo = null;
+ private String measurementPerFlowStr = new String();
/** The logger. */
private static Logger log = LoggerFactory.getLogger(FlowManager.class);
@@ -815,7 +816,7 @@
thread.start();
}
- // Want for all threads to complete
+ // Wait for all threads to complete
for (Thread thread : threads) {
try {
thread.join();
@@ -1960,12 +1961,39 @@
*/
@Override
public boolean measurementInstallPaths(Integer numThreads) {
- List<Thread> threads = new LinkedList<Thread>();
-
// Create a copy of the Flow Paths to install
final ConcurrentLinkedQueue<FlowPath> measurementProcessingPaths =
new ConcurrentLinkedQueue<FlowPath>(measurementStoredPaths);
+ /**
+ * A Thread-wrapper class for executing the threads and collecting
+ * the measurement data.
+ */
+ class MyThread extends Thread {
+ public long[] execTime = new long[2000];
+ public int samples = 0;
+ public int threadId = -1;
+ @Override
+ public void run() {
+ while (true) {
+ FlowPath flowPath = measurementProcessingPaths.poll();
+ if (flowPath == null)
+ return;
+ // Install the Flow Path
+ FlowId flowId = new FlowId();
+ String dataPathSummaryStr =
+ flowPath.dataPath().dataPathSummary();
+ long startTime = System.nanoTime();
+ addFlow(flowPath, flowId, dataPathSummaryStr);
+ long endTime = System.nanoTime();
+ execTime[samples] = endTime - startTime;
+ samples++;
+ }
+ }
+ };
+
+ List<MyThread> threads = new LinkedList<MyThread>();
+
log.debug("Measurement Installing {} flows",
measurementProcessingPaths.size());
@@ -1973,20 +2001,8 @@
// Create the threads to install the Flow Paths
//
for (int i = 0; i < numThreads; i++) {
- Thread thread = new Thread(new Runnable() {
- @Override
- public void run() {
- while (true) {
- FlowPath flowPath = measurementProcessingPaths.poll();
- if (flowPath == null)
- return;
- // Install the Flow Path
- FlowId flowId = new FlowId();
- String dataPathSummaryStr =
- flowPath.dataPath().dataPathSummary();
- addFlow(flowPath, flowId, dataPathSummaryStr);
- }
- }}, "Measurement Add Flow Path");
+ MyThread thread = new MyThread();
+ thread.threadId = i;
threads.add(thread);
}
@@ -1999,7 +2015,7 @@
thread.start();
}
- // Want for all threads to complete
+ // Wait for all threads to complete
for (Thread thread : threads) {
try {
thread.join();
@@ -2011,6 +2027,20 @@
// Record the end of processing
measurementEndTimeProcessingPaths = System.nanoTime();
+ //
+ // Prepare the string with measurement data per each Flow Path
+ // installation.
+ // The string is multiple lines: one line per Flow Path installation:
+ // ThreadAndTimePerFlow <ThreadId> <TotalThreads> <Time(ns)>
+ //
+ measurementPerFlowStr = new String();
+ String eol = System.getProperty("line.separator");
+ for (MyThread thread : threads) {
+ for (int i = 0; i < thread.samples; i++) {
+ measurementPerFlowStr += "ThreadAndTimePerFlow " + thread.threadId + " " + numThreads + " " + thread.execTime[i] + eol;
+ }
+ }
+
return true;
}
@@ -2027,6 +2057,17 @@
}
/**
+ * Get the measurement install time per Flow.
+ *
+ * @return a multi-line string with the following format per line:
+ * ThreadAndTimePerFlow <ThreadId> <TotalThreads> <Time(ns)>
+ */
+ @Override
+ public String measurementGetPerFlowInstallTime() {
+ return new String(measurementPerFlowStr);
+ }
+
+ /**
* Clear the path flows stored for measurement purpose.
*
* @return true on success, otherwise false.
@@ -2037,6 +2078,7 @@
topoRouteService.dropShortestPathTopo(measurementShortestPathTopo);
measurementStartTimeProcessingPaths = 0;
measurementEndTimeProcessingPaths = 0;
+ measurementPerFlowStr = new String();
return true;
}