diff --git a/src/DynamoCore/DynamoCore.csproj b/src/DynamoCore/DynamoCore.csproj index 5a7f450f57f..df3735cd1c3 100644 --- a/src/DynamoCore/DynamoCore.csproj +++ b/src/DynamoCore/DynamoCore.csproj @@ -142,6 +142,7 @@ limitations under the License. + diff --git a/src/DynamoCore/Models/DynamoModelEvents.cs b/src/DynamoCore/Models/DynamoModelEvents.cs index 3387c4cc170..2a381d3cbe9 100644 --- a/src/DynamoCore/Models/DynamoModelEvents.cs +++ b/src/DynamoCore/Models/DynamoModelEvents.cs @@ -320,7 +320,7 @@ public virtual void OnEvaluationCompleted(object sender, EvaluationCompletedEven { Action showFailureMessage = () => DisplayEngineFailureMessage(e.Error); OnRequestDispatcherBeginInvoke(showFailureMessage); - } + } if (EvaluationCompleted != null) EvaluationCompleted(sender, e); diff --git a/src/DynamoCore/Properties/AssemblyInfo.cs b/src/DynamoCore/Properties/AssemblyInfo.cs index fc024b12847..b236dab44c2 100644 --- a/src/DynamoCore/Properties/AssemblyInfo.cs +++ b/src/DynamoCore/Properties/AssemblyInfo.cs @@ -28,3 +28,4 @@ [assembly: InternalsVisibleTo("Dynamo.Storage")] [assembly: InternalsVisibleTo("LibraryViewExtension")] [assembly: InternalsVisibleTo("ViewExtensionLibraryTests")] +[assembly: InternalsVisibleTo("DynamoPerformanceTests")] diff --git a/src/DynamoCore/Visualization/DefaultRenderPackageFactory.cs b/src/DynamoCore/Visualization/DefaultRenderPackageFactory.cs index e11e4997b60..736d1fb450d 100644 --- a/src/DynamoCore/Visualization/DefaultRenderPackageFactory.cs +++ b/src/DynamoCore/Visualization/DefaultRenderPackageFactory.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Linq; using Autodesk.DesignScript.Interfaces; -using Dynamo.Interfaces; namespace Dynamo.Visualization { diff --git a/src/DynamoWPFCLI/GeometryHolder.cs b/src/DynamoCore/Visualization/GeometryHolder.cs similarity index 95% rename from src/DynamoWPFCLI/GeometryHolder.cs rename to src/DynamoCore/Visualization/GeometryHolder.cs index 43e5e5a69be..df92a59af04 100644 --- a/src/DynamoWPFCLI/GeometryHolder.cs +++ b/src/DynamoCore/Visualization/GeometryHolder.cs @@ -5,9 +5,8 @@ using Autodesk.DesignScript.Interfaces; using Dynamo.Graph.Nodes; using Dynamo.Models; -using Dynamo.Visualization; -namespace DynamoWPFCLI +namespace Dynamo.Visualization { internal class GeometryData { @@ -100,7 +99,7 @@ public GeometryHolder(DynamoModel model, IRenderPackageFactory factory, NodeMode // Schedule the generation of render packages for this node. NodeRenderPackagesUpdated will be // called with the render packages when they are ready. The node will be set do 'Done' if the - // sheduling for some reason is not successful (usually becuase the node have no geometry or is inivisible) + // scheduling for some reason is not successful (usually because the node have no geometry or is invisible) nodeModel.RenderPackagesUpdated += NodeRenderPackagesUpdated; if (!nodeModel.RequestVisualUpdateAsync(model.Scheduler, model.EngineController, factory, true)) { diff --git a/src/DynamoCoreWpf/Properties/AssemblyInfo.cs b/src/DynamoCoreWpf/Properties/AssemblyInfo.cs index 788c68df6d1..411017e14ef 100644 --- a/src/DynamoCoreWpf/Properties/AssemblyInfo.cs +++ b/src/DynamoCoreWpf/Properties/AssemblyInfo.cs @@ -35,3 +35,5 @@ [assembly: InternalsVisibleTo("ViewExtensionLibraryTests")] [assembly: InternalsVisibleTo("DynamoWPFCLI")] [assembly: InternalsVisibleTo("CommandLineTests")] +[assembly: InternalsVisibleTo("Watch3DNodeModelsWpf")] +[assembly: InternalsVisibleTo("DynamoPerformanceTests")] diff --git a/src/DynamoCoreWpf/ViewModels/Watch3D/DefaultWatch3DViewModel.cs b/src/DynamoCoreWpf/ViewModels/Watch3D/DefaultWatch3DViewModel.cs index 8eaef740f8b..d8b75643bc8 100644 --- a/src/DynamoCoreWpf/ViewModels/Watch3D/DefaultWatch3DViewModel.cs +++ b/src/DynamoCoreWpf/ViewModels/Watch3D/DefaultWatch3DViewModel.cs @@ -557,7 +557,7 @@ private void RegisterNodeEventHandlers(NodeModel node) RegisterPortEventHandlers(node); } - protected void UnregisterNodeEventHandlers(NodeModel node) + internal void UnregisterNodeEventHandlers(NodeModel node) { node.PropertyChanged -= OnNodePropertyChanged; node.RenderPackagesUpdated -= OnRenderPackagesUpdated; diff --git a/src/DynamoWPFCLI/DynamoWPFCLI.csproj b/src/DynamoWPFCLI/DynamoWPFCLI.csproj index c237bffe4df..6601411c21f 100644 --- a/src/DynamoWPFCLI/DynamoWPFCLI.csproj +++ b/src/DynamoWPFCLI/DynamoWPFCLI.csproj @@ -56,7 +56,6 @@ AssemblySharedInfo.cs - diff --git a/src/Libraries/Watch3DNodeModelsWpf/HelixWatch3DNodeViewModel.cs b/src/Libraries/Watch3DNodeModelsWpf/HelixWatch3DNodeViewModel.cs index 3535f55f2b6..164233abb79 100644 --- a/src/Libraries/Watch3DNodeModelsWpf/HelixWatch3DNodeViewModel.cs +++ b/src/Libraries/Watch3DNodeModelsWpf/HelixWatch3DNodeViewModel.cs @@ -32,7 +32,7 @@ public HelixWatch3DNodeViewModel(Watch3D node, Watch3DViewModelStartupParams par Name = string.Format("{0} Preview", node.GUID); } - protected override void OnWatchExecution() + protected internal override void OnWatchExecution() { var watch3D = watchModel as Watch3D; if (watch3D != null) @@ -53,7 +53,7 @@ protected override void PortConnectedHandler(PortModel arg1, ConnectorModel arg2 UpdateUpstream(); } - protected override void UpdateUpstream() + protected internal override void UpdateUpstream() { OnClear(); diff --git a/tools/Performance/DynamoPerformanceTests/DynamoPerformanceTests.csproj b/tools/Performance/DynamoPerformanceTests/DynamoPerformanceTests.csproj index 5b4a423eb23..5e72e1c3dd4 100644 --- a/tools/Performance/DynamoPerformanceTests/DynamoPerformanceTests.csproj +++ b/tools/Performance/DynamoPerformanceTests/DynamoPerformanceTests.csproj @@ -42,6 +42,12 @@ packages\CommandLineParser.2.4.3\lib\netstandard2.0\CommandLine.dll + + ..\..\..\bin\AnyCPU\$(Configuration)\DynamoCore.dll + + + ..\..\..\bin\AnyCPU\$(Configuration)\DynamoCoreWpf.dll + ..\..\..\bin\AnyCPU\$(Configuration)\DynamoCoreTests.dll @@ -228,6 +234,7 @@ + diff --git a/tools/Performance/DynamoPerformanceTests/DynamoViewPerformanceTestBase.cs b/tools/Performance/DynamoPerformanceTests/DynamoViewPerformanceTestBase.cs index 58c92f9e6d0..fe8ad05ca93 100644 --- a/tools/Performance/DynamoPerformanceTests/DynamoViewPerformanceTestBase.cs +++ b/tools/Performance/DynamoPerformanceTests/DynamoViewPerformanceTestBase.cs @@ -8,7 +8,7 @@ namespace DynamoPerformanceTests { - public class DynamoViewPerformanceTestBase : NodeViewTests + public class DynamoViewPerformanceTestBase : GrapViewTests { /// /// Override this function to preload dlls into Dynamo library @@ -60,7 +60,7 @@ public static IEnumerable PerformanceTestSource() #region Iteration setup and cleanup methods for Benchmarks /// - /// Setup method to be called before each OpenModel benchmark. + /// Setup method to be called before each OpenGraph benchmark. /// [IterationSetup(Target = nameof(OpenGraph))] public void IterationSetupOpenModelWithUI() @@ -69,15 +69,34 @@ public void IterationSetupOpenModelWithUI() } /// - /// Setup method to be called before each RunModel benchmark. + /// Setup method to be called before each RunGraph benchmark. /// [IterationSetup(Target = nameof(RunGraph))] public void IterationSetupRunModelWithUI() { Start(); + // open the dyn file + Open(DynamoFilePath); + + // Disable tessellation or rendering + DisableRendering(); + } + + /// + /// Setup method to be called before each GraphTessellationAndRendering benchmark. + /// + [IterationSetup(Target = nameof(GraphTessellationAndRendering))] + public void IterationSetupRenderGraph() + { + Start(); + //open the dyn file Open(DynamoFilePath); + // Disable tessellation or rendering + DisableRendering(); + + Run(); } /// @@ -108,6 +127,12 @@ public void RunGraph() Run(); } + [Benchmark, System.STAThread] + public void GraphTessellationAndRendering() + { + Tessellate(); + } + #endregion } } diff --git a/tools/Performance/DynamoPerformanceTests/GraphViewTests.cs b/tools/Performance/DynamoPerformanceTests/GraphViewTests.cs new file mode 100644 index 00000000000..56948ae23d9 --- /dev/null +++ b/tools/Performance/DynamoPerformanceTests/GraphViewTests.cs @@ -0,0 +1,104 @@ +using System.Collections.Generic; +using System.Threading; +using Dynamo.Graph.Workspaces; +using Dynamo.Models; +using Dynamo.Visualization; +using Dynamo.Wpf.Rendering; +using DynamoCoreWpfTests; +using DynamoCoreWpfTests.Utility; + +namespace DynamoPerformanceTests +{ + + /// + /// This class should not be used for Dynamo View unit tests but performance + /// benchmarks because other than evaluation correctness, this test class + /// focuses more on the way to get time consumption of graph evaluation, + /// tessellation and rendering + /// + public class GrapViewTests : DynamoTestUIBase + { + /// + /// Signal used for performance time measurement + /// + private static ManualResetEvent signalEvent = new ManualResetEvent(false); + + /// + /// Function used to measure file open which saved in manual mode + /// + /// + public override void Open(string path) + { + base.Open(path); + + DispatcherUtil.DoEvents(); + } + + /// + /// Call this to disable the event handler to get render package (Tessellation) + /// Rendering in helix view will also be disabled as a result of this + /// Currently only used in performance benchmarking + /// + public void DisableRendering() + { + // Dispose the background watch 3D ViewModel so no tessellation or rendering happen + foreach (var node in Model.CurrentWorkspace.Nodes) + { + ViewModel.BackgroundPreviewViewModel.UnregisterNodeEventHandlers(node); + } + } + + /// + /// Event handler for EvaluationCompleted event + /// + /// sender + /// EvaluationCompletedEventArgs + void OnGraphEvaluationCompleted(object sender, EvaluationCompletedEventArgs e) + { + if (e.EvaluationSucceeded) + { + // Signal the signalEvent ready + signalEvent.Set(); + } + } + + /// + /// Function used to measure graph run with view + /// + public override void Run() + { + // A more precise way to measure the time spent is from when + // run() called to when even EvaluationCompleted is trigger on workspace + (Model.CurrentWorkspace as HomeWorkspaceModel).EvaluationCompleted += OnGraphEvaluationCompleted; + + base.Run(); + signalEvent.WaitOne(); + signalEvent.Reset(); + // Unsubscribe + (Model.CurrentWorkspace as HomeWorkspaceModel).EvaluationCompleted -= OnGraphEvaluationCompleted; + } + + /// + /// Function used to measure graph geometry tessellation + /// + public void Tessellate() + { + var renderPackageFactory = new HelixRenderPackageFactory(); + + // A list of GeometryHolder for all the nodes belong to the graph + var nodeGeometries = new List(); + + foreach (var node in Model.CurrentWorkspace.Nodes) + { + // Each Geometry Holder will request render packages and trigger Tessellation and Rendering + nodeGeometries.Add(new GeometryHolder(Model, renderPackageFactory, node)); + } + + foreach (var holder in nodeGeometries) + { + if (holder.HasGeometry) + continue; + } + } + } +} \ No newline at end of file