Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DYN-2476] First graph run does not show execution time in TuneUp + #47

8 changes: 8 additions & 0 deletions TuneUp/ProfiledNodeViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Dynamo.Core;
using Dynamo.Graph.Nodes;

namespace TuneUp
{
public class ProfiledNodeViewModel : NotificationObject
Expand Down Expand Up @@ -130,6 +132,11 @@ public string StateDescription
}
}

/// <summary>
/// The Stopwatch to measure execution time of this node
/// </summary>
public Stopwatch Stopwatch { get; set; }
reddyashish marked this conversation as resolved.
Show resolved Hide resolved

internal NodeModel NodeModel { get; set; }

#endregion
Expand All @@ -142,6 +149,7 @@ public ProfiledNodeViewModel(NodeModel node)
{
NodeModel = node;
State = ProfiledNodeState.NotExecuted;
Stopwatch = new Stopwatch();
}

/// <summary>
Expand Down
10 changes: 8 additions & 2 deletions TuneUp/TuneUpViewExtension.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using System.Windows.Controls;
using Dynamo.Wpf.Extensions;

Expand Down Expand Up @@ -45,11 +46,12 @@ public override void Loaded(ViewLoadedParams p)
{
p.AddToExtensionsSideBar(this, TuneUpView);
ViewModel.SwitchToManualMode();
ViewModel.EnableProfiling();
ViewModel.EnableProfiling();
}
else
{
p.CloseExtensioninInSideBar(this);
ViewModel.DisableProfiling();
}
};

Expand Down Expand Up @@ -110,6 +112,10 @@ public override void Closed()
if (this.TuneUpMenuItem != null)
{
this.TuneUpMenuItem.IsChecked = false;

// Reset DataGrid sorting order & direction
ViewModel.SortingOrder = "number";
ViewModel.SortDirection = System.ComponentModel.ListSortDirection.Ascending;
}
}
}
Expand Down
1 change: 0 additions & 1 deletion TuneUp/TuneUpWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@
SelectionChanged="NodeAnalysisTable_SelectionChanged"
PreviewMouseDown="NodeAnalysisTable_PreviewMouseDown"
MouseLeave="NodeAnalysisTable_MouseLeave" >

<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
Expand Down
3 changes: 2 additions & 1 deletion TuneUp/TuneUpWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
Expand Down
137 changes: 106 additions & 31 deletions TuneUp/TuneUpWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,17 @@ public enum ProfiledNodeState
[Display(Name = "Executed On Current Run")]
ExecutedOnCurrentRun = 1,

[Display(Name = "Executed On Current Run")]
ExecutedOnCurrentRunTotal = 2,

[Display(Name = "Executed On Previous Run")]
ExecutedOnPreviousRun = 3,

[Display(Name = "Executed On Previous Run")]
ExecutedOnPreviousRun = 2,
ExecutedOnPreviousRunTotal = 4,

[Display(Name = "Not Executed")]
NotExecuted = 3,
NotExecuted = 5,
}

/// <summary>
Expand All @@ -52,6 +58,8 @@ public class TuneUpWindowViewModel : NotificationObject, IDisposable
private Dictionary<Guid, ProfiledNodeViewModel> nodeDictionary = new Dictionary<Guid, ProfiledNodeViewModel>();
private SynchronizationContext uiContext;
private bool isTuneUpChecked = false;
private ListSortDirection sortDirection;
private string sortingOrder;

/// <summary>
/// Name of the row to display current execution time
Expand Down Expand Up @@ -96,10 +104,11 @@ private HomeWorkspaceModel CurrentWorkspace
}
}
}

#endregion

#region Public Properties

/// <summary>
/// Is the recomputeAll button enabled in the UI. Users should not be able to force a
/// reset of the engine and re-execution of the graph if one is still ongoing. This causes...trouble.
Expand Down Expand Up @@ -166,6 +175,43 @@ public string TotalGraphExecutiontime
return (PreviousExecutionTimeRow?.ExecutionMilliseconds + CurrentExecutionTimeRow?.ExecutionMilliseconds).ToString() + "ms";
}
}

/// <summary>
/// Gets or sets the sorting order and toggles the sort direction.
/// </summary>
public string SortingOrder
{
get => sortingOrder;
set
{
if (sortingOrder != value)
{
sortingOrder = value;
SortDirection = ListSortDirection.Ascending;
}
else
{
SortDirection = SortDirection == ListSortDirection.Ascending
? ListSortDirection.Descending : ListSortDirection.Ascending;
}
}
}

/// <summary>
/// Gets or sets the sort direction and raises property change notification if the value changes.
/// </summary>
public ListSortDirection SortDirection
{
get => sortDirection;
set
{
if (sortDirection != value)
{
sortDirection = value;
}
}
}

#endregion

#region Constructor
Expand All @@ -183,6 +229,7 @@ public TuneUpWindowViewModel(ViewLoadedParams p)
CurrentWorkspace = p.CurrentWorkspaceModel as HomeWorkspaceModel;
}
}

#endregion

#region ProfilingMethods
Expand All @@ -193,12 +240,16 @@ public TuneUpWindowViewModel(ViewLoadedParams p)
/// </summary>
internal void ResetProfiledNodes()
{
if (CurrentWorkspace == null)
{
return;
}
nodeDictionary.Clear();
ProfiledNodes.Clear();
if (CurrentWorkspace == null) return;

// Use temporary collections to minimize UI updates
var newProfiledNodes = new ObservableCollection<ProfiledNodeViewModel>();
var newNodeDictionary = new Dictionary<Guid, ProfiledNodeViewModel>();

// Assign the new collection
ProfiledNodes = newProfiledNodes;
nodeDictionary = newNodeDictionary;

foreach (var node in CurrentWorkspace.Nodes)
{
var profiledNode = new ProfiledNodeViewModel(node);
Expand Down Expand Up @@ -262,6 +313,15 @@ internal void EnableProfiling()
RaisePropertyChanged(nameof(ProfiledNodesCollection));
}

internal void DisableProfiling()
{
if (isProfilingEnabled && CurrentWorkspace != null)
{
CurrentWorkspace.EngineController.EnableProfiling(false, CurrentWorkspace, CurrentWorkspace.Nodes);
isProfilingEnabled = false;
}
}

#endregion

#region ExecutionEvents
Expand Down Expand Up @@ -292,16 +352,10 @@ private void CurrentWorkspaceModel_EvaluationCompleted(object sender, Dynamo.Mod
RaisePropertyChanged(nameof(ProfiledNodesCollection));
RaisePropertyChanged(nameof(ProfiledNodes));

ProfiledNodesCollection.Dispatcher.Invoke(() =>
ProfiledNodesCollection.Dispatcher.InvokeAsync(() =>
{
ProfiledNodesCollection.SortDescriptions.Clear();
// Sort nodes into execution group
ProfiledNodesCollection.SortDescriptions.Add(new SortDescription(nameof(ProfiledNodeViewModel.State), ListSortDirection.Ascending));

// Sort nodes into execution order and make sure Total execution time is always bottom
ProfiledNodesCollection.SortDescriptions.Add(new SortDescription(nameof(ProfiledNodeViewModel.ExecutionOrderNumber), ListSortDirection.Descending));
if (ProfiledNodesCollection.View != null)
ProfiledNodesCollection.View.Refresh();
ApplySorting();
ProfiledNodesCollection.View.Refresh();
});
}

Expand All @@ -321,38 +375,59 @@ private void UpdateExecutionTime()
var totalSpanExecuted = new TimeSpan(ProfiledNodes.Where(n => n.WasExecutedOnLastRun).Sum(r => r.ExecutionTime.Ticks));
var totalSpanUnexecuted = new TimeSpan(ProfiledNodes.Where(n => !n.WasExecutedOnLastRun).Sum(r => r.ExecutionTime.Ticks));
ProfiledNodes.Add(new ProfiledNodeViewModel(
CurrentExecutionString, totalSpanExecuted, ProfiledNodeState.ExecutedOnCurrentRun));
CurrentExecutionString, totalSpanExecuted, ProfiledNodeState.ExecutedOnCurrentRunTotal));
ProfiledNodes.Add(new ProfiledNodeViewModel(
PreviousExecutionString, totalSpanUnexecuted, ProfiledNodeState.ExecutedOnPreviousRun));
PreviousExecutionString, totalSpanUnexecuted, ProfiledNodeState.ExecutedOnPreviousRunTotal));
}, null);
RaisePropertyChanged(nameof(TotalGraphExecutiontime));
}

/// <summary>
/// Applies the sorting logic to the ProfiledNodesCollection.
/// </summary>
public void ApplySorting()
{
ProfiledNodesCollection.SortDescriptions.Clear();

// Sort nodes into execution group
ProfiledNodesCollection.SortDescriptions.Add(new SortDescription(nameof(ProfiledNodeViewModel.State), ListSortDirection.Ascending));

// Sort nodes into execution order and make sure Total execution time is always bottom
var sortDescription = sortingOrder switch
{
"time" => new SortDescription(nameof(ProfiledNodeViewModel.ExecutionTime), sortDirection),
"name" => new SortDescription(nameof(ProfiledNodeViewModel.Name), sortDirection),
_ => new SortDescription(nameof(ProfiledNodeViewModel.ExecutionOrderNumber), sortDirection),
};
ProfiledNodesCollection.SortDescriptions.Add(sortDescription);
}

internal void OnNodeExecutionBegin(NodeModel nm)
{
var profiledNode = nodeDictionary[nm.GUID];
profiledNode.Stopwatch.Start();
profiledNode.State = ProfiledNodeState.Executing;
RaisePropertyChanged(nameof(ProfiledNodesCollection));
}

internal void OnNodeExecutionEnd(NodeModel nm)
{
var profiledNode = nodeDictionary[nm.GUID];
if (executionTimeData != null)
profiledNode.Stopwatch.Stop();
var executionTime = profiledNode.Stopwatch.Elapsed;

if (executionTime > TimeSpan.Zero)
{
var executionTime = executionTimeData.NodeExecutionTime(nm);
if (executionTime != null)
{
profiledNode.ExecutionTime = (TimeSpan)executionTime;
}
profiledNode.ExecutionTime = executionTime;

if (!profiledNode.WasExecutedOnLastRun)
{
profiledNode.ExecutionOrderNumber = executedNodesNum++;
}
}

profiledNode.Stopwatch.Reset();
profiledNode.WasExecutedOnLastRun = true;
profiledNode.State = ProfiledNodeState.ExecutedOnCurrentRun;
RaisePropertyChanged(nameof(ProfiledNodesCollection));
}

#endregion
Expand Down Expand Up @@ -420,7 +495,7 @@ private void ManageWorkspaceEvents(HomeWorkspaceModel workspace, bool subscribe)
node.NodeExecutionBegin += OnNodeExecutionBegin;
node.NodeExecutionEnd += OnNodeExecutionEnd;
}
ResetProfiledNodes();
ResetProfiledNodes();
}
// Unsubscribe to workspace events
else
Expand All @@ -435,7 +510,7 @@ private void ManageWorkspaceEvents(HomeWorkspaceModel workspace, bool subscribe)
node.NodeExecutionBegin -= OnNodeExecutionBegin;
node.NodeExecutionEnd -= OnNodeExecutionEnd;
}
}
}
executedNodesNum = 0;
}

Expand Down Expand Up @@ -478,4 +553,4 @@ public void ExportToCsv()

#endregion
}
}
}