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: