* Add performance monitoring points
* Move the code for sending notifications for deleted Flow Entries
  outside of a loop, so the corresponding performance measurements are
  more accurate.
diff --git a/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java b/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
index c195f82..7e09982 100644
--- a/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
+++ b/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
@@ -44,6 +44,8 @@
 import com.hazelcast.core.IMap;
 import com.hazelcast.instance.GroupProperties;
 
+import net.onrc.onos.ofcontroller.flowmanager.PerformanceMonitor;
+
 /**
  * A datagrid service that uses Hazelcast as a datagrid.
  * The relevant data is stored in the Hazelcast datagrid and shared as
@@ -448,6 +450,7 @@
 	 */
 	@Override
 	public void entryRemoved(EntryEvent<String, byte[]> event) {
+	    PerformanceMonitor.start("TopologyEntryRemoved.NotificationReceived");
 	    byte[] valueBytes = event.getValue();
 
 	    //
@@ -459,6 +462,8 @@
 		kryo.readObject(input, TopologyElement.class);
 	    kryoFactory.deleteKryo(kryo);
 	    flowEventHandlerService.notificationRecvTopologyElementRemoved(topologyElement);
+	    PerformanceMonitor.stop("TopologyEntryRemoved.NotificationReceived");
+	    PerformanceMonitor.report();
 	}
 
 	/**
diff --git a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
index ea547fc..994c741 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
@@ -43,6 +43,8 @@
 import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
 import net.onrc.onos.registry.controller.RegistryException;
 
+import net.onrc.onos.ofcontroller.flowmanager.PerformanceMonitor;
+
 import org.openflow.protocol.OFPhysicalPort;
 import org.openflow.util.HexString;
 import org.slf4j.Logger;
@@ -351,12 +353,16 @@
 	@Override
 	public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
 		// Remove all links that might be connected already
+		PerformanceMonitor.start("SwitchPortRemoved.DbAccess");
+
 		List<Link> links = linkStore.getLinks(switchId, port.getPortNumber());
 		// Remove all reverse links as well
 		List<Link> reverseLinks = linkStore.getReverseLinks(switchId, port.getPortNumber());
 		links.addAll(reverseLinks);
 
 		if (swStore.deletePort(HexString.toHexString(switchId), port.getPortNumber())) {
+		    PerformanceMonitor.stop("SwitchPortRemoved.DbAccess");
+		    PerformanceMonitor.start("SwitchPortRemoved.NotificationSend");
 		    // TODO publish DELETE_PORT event here
 		    TopologyElement topologyElement =
 			new TopologyElement(switchId, port.getPortNumber());
@@ -371,6 +377,8 @@
 						link.getDstPort());
 			datagridService.notificationSendTopologyElementRemoved(topologyElementLink);
 		    }
+		    PerformanceMonitor.stop("SwitchPortRemoved.NotificationSend");
+		    PerformanceMonitor.report();
 		}
 	}
 
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
index 931bdd1..8806572 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
@@ -286,6 +286,8 @@
 
 	if (enableOnrc2014MeasurementsFlows) {
 
+	    PerformanceMonitor.start("EventHandler.ProcessAllEvents");
+
 	    if (topologyEvents.isEmpty() && flowIdEvents.isEmpty() &&
 		switchDpidEvents.isEmpty()) {
 		return;		// Nothing to do
@@ -300,9 +302,12 @@
 	    processFlowIdEvents(mySwitches);
 
 	    // Fetch the topology
+	    PerformanceMonitor.start("EventHandler.ReadTopology");
 	    processTopologyEvents();
+	    PerformanceMonitor.stop("EventHandler.ReadTopology");
 
 	    // Recompute all affected Flow Paths and keep only the modified
+	    PerformanceMonitor.start("EventHandler.RecomputeFlows");
 	    for (FlowPath flowPath : shouldRecomputeFlowPaths.values()) {
 		if (recomputeFlowPath(flowPath))
 		    modifiedFlowPaths.put(flowPath.flowId().value(), flowPath);
@@ -317,10 +322,12 @@
 		    }
 		}
 	    }
+	    PerformanceMonitor.stop("EventHandler.RecomputeFlows");
 
 	    //
 	    // Push the modified state to the database
 	    //
+	    PerformanceMonitor.start("EventHandler.WriteFlowsToDb");
 	    for (FlowPath flowPath : modifiedFlowPaths.values()) {
 		//
 		// Delete the Flow Path from the Network Map
@@ -331,10 +338,17 @@
 		    // TODO: For now the deleting of a Flow Path is blocking
 		    ParallelFlowDatabaseOperation.deleteFlow(dbHandler,
 							     flowPath.flowId());
+		    //
+		    // NOTE: For now the sending of the notifications
+		    // is outside of this loop, so the performance measurements
+		    // are more accurate.
+		    //
+		    /*
 		    // Send the notifications for the deleted Flow Entries
 		    for (FlowEntry flowEntry : flowPath.flowEntries()) {
 			datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
 		    }
+		    */
 
 		    continue;
 		}
@@ -346,6 +360,23 @@
 		ParallelFlowDatabaseOperation.addFlow(dbHandler, flowPath,
 						      datagridService);
 	    }
+	    PerformanceMonitor.stop("EventHandler.WriteFlowsToDb");
+
+	    //
+	    // Send the notifications for the deleted Flow Entries
+	    // NOTE: This code was pulled outside of the above loop,
+	    // so the performance measurements are more accurate.
+	    //
+	    PerformanceMonitor.start("EventHandler.NotificationSend.FlowEntryRemoved");
+	    for (FlowPath flowPath : modifiedFlowPaths.values()) {
+		if (flowPath.flowPathUserState() ==
+		    FlowPathUserState.FP_USER_DELETE) {
+		    for (FlowEntry flowEntry : flowPath.flowEntries()) {
+			datagridService.notificationSendFlowEntryRemoved(flowEntry.flowEntryId());
+		    }
+		}
+	    }
+	    PerformanceMonitor.stop("EventHandler.WriteFlowsToDb");
 
 	    // Cleanup
 	    topologyEvents.clear();
@@ -357,6 +388,9 @@
 	    shouldRecomputeFlowPaths.clear();
 	    modifiedFlowPaths.clear();
 
+	    PerformanceMonitor.stop("EventHandler.ProcessAllEvents");
+	    PerformanceMonitor.report();
+
 	    return;
 	}
 
@@ -1365,9 +1399,12 @@
     @Override
     public void notificationRecvFlowEntryAdded(FlowEntry flowEntry) {
 	if (enableOnrc2014MeasurementsFlows) {
+	    PerformanceMonitor.start("EventHandler.AddFlowEntryToSwitch");
 	    Collection entries = new ArrayList();
 	    entries.add(flowEntry);
 	    flowManager.pushModifiedFlowEntriesToSwitches(entries);
+	    PerformanceMonitor.stop("EventHandler.AddFlowEntryToSwitch");
+	    PerformanceMonitor.report();
 	    return;
 	}
 
@@ -1384,6 +1421,7 @@
     @Override
     public void notificationRecvFlowEntryRemoved(FlowEntry flowEntry) {
 	if (enableOnrc2014MeasurementsFlows) {
+	    PerformanceMonitor.start("EventHandler.RemoveFlowEntryFromSwitch");
 	    //
 	    // NOTE: Must update the state to DELETE, because
 	    // the notification contains the original state.
@@ -1393,6 +1431,8 @@
 	    Collection entries = new ArrayList();
 	    entries.add(flowEntry);
 	    flowManager.pushModifiedFlowEntriesToSwitches(entries);
+	    PerformanceMonitor.stop("EventHandler.RemoveFlowEntryFromSwitch");
+	    PerformanceMonitor.report();
 	    return;
 	}