diff --git a/TuneUp/ProfiledNodeViewModel.cs b/TuneUp/ProfiledNodeViewModel.cs
index e6f06d2..09a9252 100644
--- a/TuneUp/ProfiledNodeViewModel.cs
+++ b/TuneUp/ProfiledNodeViewModel.cs
@@ -172,6 +172,20 @@ public int ExecutionMilliseconds
}
private int executionMilliseconds;
+ ///
+ /// The total execution time of this group in milliseconds
+ ///
+ public int GroupExecutionMilliseconds
+ {
+ get => groupExecutionMilliseconds;
+ set
+ {
+ groupExecutionMilliseconds = value;
+ RaisePropertyChanged(nameof(GroupExecutionMilliseconds));
+ }
+ }
+ private int groupExecutionMilliseconds;
+
///
/// Indicates whether this node was executed on the most recent graph run
///
@@ -245,7 +259,6 @@ public bool ShowGroupIndicator
}
private bool showGroupIndicator;
-
///
/// The background brush for this node
/// If this node represents a group, it inherits the background color from the associated AnnotationModel
@@ -333,7 +346,7 @@ internal void ResetGroupProperties()
GroupGUID = Guid.Empty;
GroupName = string.Empty;
GroupExecutionOrderNumber = null;
- GroupExecutionTime = TimeSpan.Zero;
+ GroupExecutionMilliseconds = 0;
}
internal void ApplyGroupProperties(ProfiledNodeViewModel profiledGroup)
@@ -359,12 +372,10 @@ public ProfiledNodeViewModel(NodeModel node)
/// An alternative constructor which we can customize data for display in TuneUp datagrid
///
/// row display name
- /// execution time in ms
/// state which determine grouping
- public ProfiledNodeViewModel(string name, TimeSpan exTimeSum, ProfiledNodeState state)
+ public ProfiledNodeViewModel(string name, ProfiledNodeState state)
{
this.Name = name;
- this.ExecutionTime = exTimeSum;
State = state;
}
diff --git a/TuneUp/TuneUpWindowViewModel.cs b/TuneUp/TuneUpWindowViewModel.cs
index 81c7716..5487878 100644
--- a/TuneUp/TuneUpWindowViewModel.cs
+++ b/TuneUp/TuneUpWindowViewModel.cs
@@ -540,10 +540,9 @@ private void CalculateGroupNodes()
ProfiledNodeViewModel groupTotalTimeNode = null;
bool groupIsRenamed = false;
- // Reset group state
+ // Reset group state and execution time
profiledGroup.State = profiledNode.State;
- profiledGroup.GroupExecutionTime = TimeSpan.Zero; // Reset execution time
- profiledGroup.ExecutionMilliseconds = 0; // Reset UI execution time
+ profiledNode.GroupExecutionMilliseconds = 0;
MoveNodeToCollection(profiledGroup, ProfiledNodesLatestRun); // Ensure the profiledGroup is in latest run
// Check if the group has been renamed
@@ -565,8 +564,7 @@ private void CalculateGroupNodes()
else if (processedNodes.Add(node))
{
// Update group state, execution order, and execution time
- profiledGroup.GroupExecutionTime += node.ExecutionTime; // accurate, for sorting
- profiledGroup.ExecutionMilliseconds += node.ExecutionMilliseconds; // rounded, for display in UI
+ profiledGroup.GroupExecutionMilliseconds += node.ExecutionMilliseconds;
node.GroupExecutionOrderNumber = groupExecutionCounter;
node.ShowGroupIndicator = ShowGroups;
if (groupIsRenamed)
@@ -578,7 +576,6 @@ private void CalculateGroupNodes()
// Update the properties of the group node
profiledGroup.GroupExecutionOrderNumber = groupExecutionCounter++;
- profiledGroup.ExecutionTime = profiledGroup.GroupExecutionTime;
profiledGroup.WasExecutedOnLastRun = true;
@@ -591,7 +588,7 @@ private void CalculateGroupNodes()
// Update the groupExecutionTime for all nodes of the group for the purposes of sorting
foreach (var node in nodesInGroup)
{
- node.GroupExecutionTime = profiledGroup.GroupExecutionTime;
+ node.GroupExecutionMilliseconds = profiledGroup.GroupExecutionMilliseconds;
}
}
}
@@ -601,7 +598,7 @@ private void CalculateGroupNodes()
!profiledNode.IsGroupExecutionTime)
{
profiledNode.GroupExecutionOrderNumber = groupExecutionCounter++;
- profiledNode.GroupExecutionTime = profiledNode.ExecutionTime;
+ profiledNode.GroupExecutionMilliseconds = profiledNode.ExecutionMilliseconds;
}
}
@@ -629,10 +626,10 @@ internal void OnNodeExecutionEnd(NodeModel nm)
if (executionTime > TimeSpan.Zero)
{
- profiledNode.ExecutionTime = executionTime;
// Assign execution time and manually set the execution milliseconds value
// so that group node execution time is based on rounded millisecond values.
- profiledNode.ExecutionMilliseconds = (int)Math.Round(executionTime.TotalMilliseconds);
+ // Nodes should display at least 1ms execution time if they are executed.
+ profiledNode.ExecutionMilliseconds = Math.Max(1, (int)Math.Round(executionTime.TotalMilliseconds));
if (!profiledNode.WasExecutedOnLastRun)
{
@@ -741,18 +738,13 @@ internal void OnGroupPropertyChanged(object sender, PropertyChangedEventArgs e)
var totalExecutionMilliseconds = existingProfiledNodesInGroup
.Where(n => !n.IsGroupExecutionTime)
.Sum(n => n.ExecutionMilliseconds);
- var totalExecutionTime = existingProfiledNodesInGroup
- .Where(n => !n.IsGroupExecutionTime)
- .Select(n => n.ExecutionTime)
- .Aggregate(TimeSpan.Zero, (sum, next) => sum + next);
- profiledGroup.ExecutionMilliseconds = totalExecutionMilliseconds;
- profiledGroup.GroupExecutionTime = totalExecutionTime;
+ profiledGroup.ExecutionMilliseconds = profiledGroup.GroupExecutionMilliseconds = totalExecutionMilliseconds;
// update the grouped nodes
foreach (var profiledNode in existingProfiledNodesInGroup)
{
- profiledNode.GroupExecutionTime = totalExecutionTime;
+ profiledNode.GroupExecutionMilliseconds = totalExecutionMilliseconds;
if (profiledNode.IsGroupExecutionTime)
{
profiledNode.ExecutionMilliseconds = totalExecutionMilliseconds;
@@ -893,7 +885,7 @@ private void OnCurrentWorkspaceCleared(IWorkspaceModel workspace)
private ProfiledNodeViewModel CreateGroupTotalTimeNode(ProfiledNodeViewModel profiledGroup)
{
var groupTotalTimeNode = new ProfiledNodeViewModel(
- ProfiledNodeViewModel.GroupExecutionTimeString, TimeSpan.Zero, ProfiledNodeState.NotExecuted)
+ ProfiledNodeViewModel.GroupExecutionTimeString, ProfiledNodeState.NotExecuted)
{
GroupGUID = profiledGroup.GroupGUID,
GroupName = profiledGroup.GroupName,
@@ -912,8 +904,7 @@ private ProfiledNodeViewModel CreateGroupTotalTimeNode(ProfiledNodeViewModel pro
private void UpdateGroupTotalTimeNodeProperties(ProfiledNodeViewModel groupTotalTimeNode, ProfiledNodeViewModel profiledGroup)
{
groupTotalTimeNode.State = profiledGroup.State;
- groupTotalTimeNode.GroupExecutionTime = profiledGroup.GroupExecutionTime; // Accurate, for sorting
- groupTotalTimeNode.ExecutionMilliseconds = profiledGroup.ExecutionMilliseconds; // Rounded, for display in UI
+ groupTotalTimeNode.GroupExecutionMilliseconds = groupTotalTimeNode.ExecutionMilliseconds = profiledGroup.GroupExecutionMilliseconds;
groupTotalTimeNode.GroupExecutionOrderNumber = profiledGroup.GroupExecutionOrderNumber;
groupTotalTimeNode.WasExecutedOnLastRun = true;
@@ -1034,15 +1025,15 @@ public void ApplyCustomSorting(CollectionViewSource collection, string explicitS
case SortByTime:
if (showGroups)
{
- collection.SortDescriptions.Add(new SortDescription(nameof(ProfiledNodeViewModel.GroupExecutionTime), sortDirection));
+ collection.SortDescriptions.Add(new SortDescription(nameof(ProfiledNodeViewModel.GroupExecutionMilliseconds), sortDirection));
collection.SortDescriptions.Add(new SortDescription(nameof(ProfiledNodeViewModel.GroupGUID), sortDirection));
collection.SortDescriptions.Add(new SortDescription(nameof(ProfiledNodeViewModel.IsGroup), ListSortDirection.Descending));
collection.SortDescriptions.Add(new SortDescription(nameof(ProfiledNodeViewModel.IsGroupExecutionTime), ListSortDirection.Ascending));
- collection.SortDescriptions.Add(new SortDescription(nameof(ProfiledNodeViewModel.ExecutionTime), sortDirection));
+ collection.SortDescriptions.Add(new SortDescription(nameof(ProfiledNodeViewModel.ExecutionMilliseconds), sortDirection));
}
else
{
- collection.SortDescriptions.Add(new SortDescription(nameof(ProfiledNodeViewModel.ExecutionTime), sortDirection));
+ collection.SortDescriptions.Add(new SortDescription(nameof(ProfiledNodeViewModel.ExecutionMilliseconds), sortDirection));
}
break;
case SortByName: