diff --git a/src/DynamoCore/Engine/Profiling/NodeProfilingData.cs b/src/DynamoCore/Engine/Profiling/NodeProfilingData.cs index 640ce25ab0b..5abbf11f6a7 100644 --- a/src/DynamoCore/Engine/Profiling/NodeProfilingData.cs +++ b/src/DynamoCore/Engine/Profiling/NodeProfilingData.cs @@ -33,10 +33,12 @@ private void RecordEvaluationState(object data) if (!startTime.HasValue) { startTime = DateTime.Now; + node.OnNodeExecutionBegin(); return; } endTime = DateTime.Now; + node.OnNodeExecutionEnd(); } internal TimeSpan? ExecutionTime diff --git a/src/DynamoCore/Graph/Nodes/NodeModel.cs b/src/DynamoCore/Graph/Nodes/NodeModel.cs index 34ec89acd92..4c299b34b8f 100644 --- a/src/DynamoCore/Graph/Nodes/NodeModel.cs +++ b/src/DynamoCore/Graph/Nodes/NodeModel.cs @@ -135,6 +135,28 @@ private void OnDispatchedToUI(object sender, UIDispatcherEventArgs e) /// public event Action PortDisconnected; + /// + /// Event triggered before a node is executed. + /// Note: This event will only be triggered when profiling is active. + /// + public event Action NodeExecutionBegin; + + internal void OnNodeExecutionBegin() + { + NodeExecutionBegin?.Invoke(this); + } + + /// + /// Event triggered after a node is executed. + /// Note: This event will only be triggered when profiling is active. + /// + public event Action NodeExecutionEnd; + + internal void OnNodeExecutionEnd() + { + NodeExecutionEnd?.Invoke(this); + } + #endregion #region public properties diff --git a/test/DynamoCoreTests/ProfilingTest.cs b/test/DynamoCoreTests/ProfilingTest.cs index d7af5ea8a00..3ae53f9d3d0 100644 --- a/test/DynamoCoreTests/ProfilingTest.cs +++ b/test/DynamoCoreTests/ProfilingTest.cs @@ -1,9 +1,11 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Linq; using Dynamo.Graph.Workspaces; using Dynamo.Models; +using Dynamo.Graph.Nodes; using NUnit.Framework; namespace Dynamo.Tests @@ -94,5 +96,58 @@ public void TestProfilingSingleNodePublicMethodsOnly() Assert.IsNotNull(profilingData.NodeExecutionTime(node)); Assert.Greater(profilingData.NodeExecutionTime(node)?.Ticks, 0); } + + private static List executingNodes = new List(); + private static int nodeExecutionBeginCount = 0; + private static int nodeExecutionEndCount = 0; + + private static void onNodeExectuionBegin(NodeModel model) + { + // Assert that the node has ot been executed more than once + CollectionAssert.DoesNotContain(executingNodes, model.GUID); + + executingNodes.Add(model.GUID); + nodeExecutionBeginCount++; + } + + private static void onNodeExectuionEnd(NodeModel model) + { + // Assert that the node ending execution had the begin exectuion event fired previously + CollectionAssert.Contains(executingNodes, model.GUID); + + nodeExecutionEndCount++; + } + + [Test] + public void TestNodeExecutionEvents() + { + // Note: This test file is saved in manual run mode + string openPath = Path.Combine(TestDirectory, @"core\profiling\createSomePoints.dyn"); + OpenModel(openPath); + + var nodes = CurrentDynamoModel.CurrentWorkspace.Nodes; + foreach(var node in nodes) + { + node.NodeExecutionBegin += onNodeExectuionBegin; + node.NodeExecutionEnd += onNodeExectuionEnd; + } + + // Currently the node execution begin/end events are only enabled when profiling is enabled + var engineController = CurrentDynamoModel.EngineController; + var homeWorkspace = CurrentDynamoModel.Workspaces.OfType().FirstOrDefault(); + engineController.EnableProfiling(true, homeWorkspace, nodes); + + BeginRun(); + + // Assert that all nodes were executed and the begin and end events were fired as expectd + Assert.AreEqual(4, nodeExecutionBeginCount); + Assert.AreEqual(4, nodeExecutionEndCount); + + foreach (var node in nodes) + { + node.NodeExecutionBegin -= onNodeExectuionBegin; + node.NodeExecutionEnd -= onNodeExectuionEnd; + } + } } }