Skip to content

Commit

Permalink
Update TuneUpWindowViewModel.cs
Browse files Browse the repository at this point in the history
  • Loading branch information
ivaylo-matov committed Nov 19, 2024
1 parent f20764f commit 52ac350
Showing 1 changed file with 100 additions and 105 deletions.
205 changes: 100 additions & 105 deletions TuneUp/TuneUpWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -433,11 +433,6 @@ internal void DisableProfiling()

private void CurrentWorkspaceModel_EvaluationStarted(object sender, EventArgs e)
{
// Store nodes in temporary HashSets to batch the updates and avoid immediate UI refreshes.
tempProfiledNodesLatestRun = ProfiledNodesLatestRun.ToHashSet();
tempProfiledNodesPreviousRun = ProfiledNodesPreviousRun.ToHashSet();
tempProfiledNodesNotExecuted = ProfiledNodesNotExecuted.ToHashSet();

IsRecomputeEnabled = false;
foreach (var node in nodeDictionary.Values)
{
Expand All @@ -452,7 +447,7 @@ private void CurrentWorkspaceModel_EvaluationStarted(object sender, EventArgs e)
// Move to CollectionPreviousRun
if (node.State == ProfiledNodeState.ExecutedOnPreviousRun)
{
MoveNodeToTempCollection(node, tempProfiledNodesPreviousRun);
MoveNodeToCollection(node, ProfiledNodesPreviousRun);
}
}
executedNodesNum = 1;
Expand All @@ -464,27 +459,13 @@ private void CurrentWorkspaceModel_EvaluationCompleted(object sender, Dynamo.Mod
Task.Run(() =>
{
IsRecomputeEnabled = true;

CalculateGroupNodes();
UpdateExecutionTime();
UpdateTableVisibility();

uiContext.Post(_ =>
{
// Swap references instead of clearing and re-adding nodes
ProfiledNodesLatestRun.Clear();
foreach (var node in tempProfiledNodesLatestRun)
{
ProfiledNodesLatestRun.Add(node);
}
ProfiledNodesPreviousRun.Clear();
foreach (var node in tempProfiledNodesPreviousRun)
{
ProfiledNodesPreviousRun.Add(node);
}
ProfiledNodesNotExecuted.Clear();
foreach (var node in tempProfiledNodesNotExecuted)
{
ProfiledNodesNotExecuted.Add(node);
}

RaisePropertyChanged(nameof(ProfiledNodesCollectionLatestRun));
RaisePropertyChanged(nameof(ProfiledNodesCollectionPreviousRun));
RaisePropertyChanged(nameof(ProfiledNodesCollectionNotExecuted));
Expand All @@ -495,15 +476,6 @@ private void CurrentWorkspaceModel_EvaluationCompleted(object sender, Dynamo.Mod
ProfiledNodesCollectionLatestRun.View?.Refresh();
ProfiledNodesCollectionPreviousRun.View?.Refresh();
ProfiledNodesCollectionNotExecuted.View?.Refresh();

// Update execution time and table visibility
UpdateExecutionTime();
UpdateTableVisibility();

// Clear temporary collections
tempProfiledNodesLatestRun = new HashSet<ProfiledNodeViewModel>();
tempProfiledNodesPreviousRun = new HashSet<ProfiledNodeViewModel>();
tempProfiledNodesNotExecuted = new HashSet<ProfiledNodeViewModel>();
}, null);
});
}
Expand All @@ -514,19 +486,23 @@ private void CurrentWorkspaceModel_EvaluationCompleted(object sender, Dynamo.Mod
/// </summary>
private void UpdateExecutionTime()
{
// After each evaluation, manually update execution time column(s)
// Calculate total execution times using rounded node execution times, not exact values.
int totalLatestRun = ProfiledNodesLatestRun
.Where(n => n.WasExecutedOnLastRun && !n.IsGroup && !n.IsGroupExecutionTime)
.Sum(r => r?.ExecutionMilliseconds ?? 0);
int previousLatestRun = ProfiledNodesPreviousRun
.Where(n => !n.WasExecutedOnLastRun && !n.IsGroup && !n.IsGroupExecutionTime)
.Sum(r => r?.ExecutionMilliseconds ?? 0);

// Update latest and previous run times
latestGraphExecutionTime = totalLatestRun.ToString();
previousGraphExecutionTime = previousLatestRun.ToString();
totalGraphExecutionTime = (totalLatestRun + previousLatestRun).ToString();
// Reset execution time
uiContext.Send(
x =>
{ // After each evaluation, manually update execution time column(s)
// Calculate total execution times using rounded node execution times, not exact values.
int totalLatestRun = ProfiledNodesLatestRun
.Where(n => n.WasExecutedOnLastRun && !n.IsGroup && !n.IsGroupExecutionTime)
.Sum(r => r?.ExecutionMilliseconds ?? 0);
int previousLatestRun = ProfiledNodesPreviousRun
.Where(n => !n.WasExecutedOnLastRun && !n.IsGroup && !n.IsGroupExecutionTime)
.Sum(r => r?.ExecutionMilliseconds ?? 0);

// Update latest and previous run times
latestGraphExecutionTime = totalLatestRun.ToString();
previousGraphExecutionTime = previousLatestRun.ToString();
totalGraphExecutionTime = (totalLatestRun + previousLatestRun).ToString();
}, null);

RaisePropertyChanged(nameof(TotalGraphExecutionTime));
RaisePropertyChanged(nameof(LatestGraphExecutionTime));
Expand All @@ -540,50 +516,59 @@ private void UpdateExecutionTime()
/// </summary>
private void CalculateGroupNodes()
{
// Clean the collections from all group and time nodesB
foreach (var node in groupDictionary.Values)
Task.Run(() =>
{
RemoveNodeFromState(node, node.State, GetTempCollectionFromState);

if (groupModelDictionary.TryGetValue(node.GroupGUID, out var groupNodes))
// Apply all removals and additions on the UI thread
uiContext.Post(_ =>
{
groupNodes.Remove(node);
}
}
groupDictionary.Clear();
// Clean the collections from all group and time nodes
foreach (var node in groupDictionary.Values)
{
RemoveNodeFromStateCollection(node, node.State);

// Create group and time nodes for latest and previous runs
CreateGroupNodesForCollection(tempProfiledNodesLatestRun);
CreateGroupNodesForCollection(tempProfiledNodesPreviousRun);
if (groupModelDictionary.TryGetValue(node.GroupGUID, out var groupNodes))
{
groupNodes.Remove(node);
}
}
groupDictionary.Clear();

// Create group nodes for not executed
var processedNodesNotExecuted = new HashSet<ProfiledNodeViewModel>();
// Create group and time nodes for latest and previous runs
CreateGroupNodesForCollection(ProfiledNodesLatestRun);
CreateGroupNodesForCollection(ProfiledNodesPreviousRun);

// Create a copy of ProfiledNodesNotExecuted to iterate over
var profiledNodesCopy = tempProfiledNodesNotExecuted.ToList();
// Create group nodes for not executed
var processedNodesNotExecuted = new HashSet<ProfiledNodeViewModel>();

foreach (var pNode in profiledNodesCopy)
{
if (pNode.GroupGUID != Guid.Empty && !processedNodesNotExecuted.Contains(pNode))
{
// get the other nodes from this group
var nodesInGroup = tempProfiledNodesNotExecuted
.Where(n => n.GroupGUID == pNode.GroupGUID)
.ToList();
// Create a copy of ProfiledNodesNotExecuted to iterate over
var profiledNodesCopy = ProfiledNodesNotExecuted.ToList();

foreach (var node in nodesInGroup)
foreach (var pNode in profiledNodesCopy)
{
processedNodesNotExecuted.Add(node);
if (pNode.GroupGUID != Guid.Empty && !processedNodesNotExecuted.Contains(pNode))
{
// get the other nodes from this group
var nodesInGroup = ProfiledNodesNotExecuted
.Where(n => n.GroupGUID == pNode.GroupGUID)
.ToList();

foreach (var node in nodesInGroup)
{
processedNodesNotExecuted.Add(node);
}

// create new group node
var pGroup = CreateAndRegisterGroupNode(pNode);
uiContext.Send(_ => ProfiledNodesNotExecuted.Add(pGroup), null);
}
}

// create new group node
var pGroup = CreateAndRegisterGroupNode(pNode);
tempProfiledNodesNotExecuted.Add(pGroup);
}
}
RefreshGroupNodeUI();
}, null);
});
}

private void CreateGroupNodesForCollection(HashSet<ProfiledNodeViewModel> collection)
private void CreateGroupNodesForCollection(ObservableCollection<ProfiledNodeViewModel> collection)
{
int executionCounter = 1;
var processedNodes = new HashSet<ProfiledNodeViewModel>();
Expand Down Expand Up @@ -660,7 +645,7 @@ internal void OnNodeExecutionEnd(NodeModel nm)
{
profiledNode.ExecutionOrderNumber = executedNodesNum++;
// Move to collection LatestRun
MoveNodeToTempCollection(profiledNode, tempProfiledNodesLatestRun);
MoveNodeToCollection(profiledNode, ProfiledNodesLatestRun);
}
}

Expand Down Expand Up @@ -890,7 +875,7 @@ private void CurrentWorkspaceModel_NodeRemoved(NodeModel node)
node.NodeExecutionEnd -= OnNodeExecutionEnd;
node.PropertyChanged -= OnNodePropertyChanged;

RemoveNodeFromState(profiledNode, profiledNode.State, GetObservableCollectionFromState);
RemoveNodeFromStateCollection(profiledNode, profiledNode.State);

//Recalculate the execution times
UpdateExecutionTime();
Expand Down Expand Up @@ -1000,7 +985,7 @@ private void CurrentWorkspaceModel_GroupRemoved(AnnotationModel group)
// Remove the group and time nodes
foreach (var node in gNodes)
{
RemoveNodeFromState(node, node.State, GetObservableCollectionFromState);
RemoveNodeFromStateCollection(node, node.State);
groupDictionary.Remove(node.NodeGUID);
}

Expand Down Expand Up @@ -1172,11 +1157,6 @@ private void InitializeCollectionsAndDictionaries()
ProfiledNodesPreviousRun?.Clear();
ProfiledNodesNotExecuted?.Clear();

// Clear temporary collections
tempProfiledNodesLatestRun = new HashSet<ProfiledNodeViewModel>();
tempProfiledNodesPreviousRun = new HashSet<ProfiledNodeViewModel>();
tempProfiledNodesNotExecuted = new HashSet<ProfiledNodeViewModel>();

// Reset execution time stats
LatestGraphExecutionTime = PreviousGraphExecutionTime = TotalGraphExecutionTime = defaultExecutionTime;

Expand All @@ -1185,6 +1165,13 @@ private void InitializeCollectionsAndDictionaries()
ProfiledNodesPreviousRun = ProfiledNodesPreviousRun ?? new ObservableCollection<ProfiledNodeViewModel>();
ProfiledNodesNotExecuted = ProfiledNodesNotExecuted ?? new ObservableCollection<ProfiledNodeViewModel>();

collectionMapping = new Dictionary<ObservableCollection<ProfiledNodeViewModel>, CollectionViewSource>
{
{ ProfiledNodesLatestRun, ProfiledNodesCollectionLatestRun },
{ ProfiledNodesPreviousRun, ProfiledNodesCollectionPreviousRun },
{ ProfiledNodesNotExecuted, ProfiledNodesCollectionNotExecuted }
};

nodeDictionary = new Dictionary<Guid, ProfiledNodeViewModel>();
groupDictionary = new Dictionary<Guid, ProfiledNodeViewModel>();
groupModelDictionary = new Dictionary<Guid, List<ProfiledNodeViewModel>>();
Expand Down Expand Up @@ -1285,16 +1272,6 @@ private ObservableCollection<ProfiledNodeViewModel> GetObservableCollectionFromS
else return ProfiledNodesNotExecuted;
}

/// <summary>
/// Returns the appropriate ObservableCollection based on the node's profiling state.
/// </summary>
private HashSet<ProfiledNodeViewModel> GetTempCollectionFromState(ProfiledNodeState state)
{
if (state == ProfiledNodeState.ExecutedOnCurrentRun) return tempProfiledNodesLatestRun;
else if (state == ProfiledNodeState.ExecutedOnPreviousRun) return tempProfiledNodesPreviousRun;
else return tempProfiledNodesNotExecuted;
}

/// <summary>
/// Updates the group visibility, refreshes the collection view, and applies appropriate sorting for the given nodes.
/// </summary>
Expand Down Expand Up @@ -1429,26 +1406,33 @@ private void SortCollectionViewForProfiledNodesCollection(ObservableCollection<P
}

/// <summary>
/// Moves a node between HashSets, removing it from all HashSets and adding it to the target HashSet if provided.
/// Moves a node between collections, removing it from all collections and adding it to the target collection if provided.
/// </summary>
private void MoveNodeToTempCollection(ProfiledNodeViewModel profiledNode, HashSet<ProfiledNodeViewModel> targetCollection)
private void MoveNodeToCollection(ProfiledNodeViewModel profiledNode, ObservableCollection<ProfiledNodeViewModel> targetCollection)
{
var collections = new[] { tempProfiledNodesLatestRun, tempProfiledNodesPreviousRun, tempProfiledNodesNotExecuted };

foreach (var collection in collections)
Task.Run(() =>
{
collection?.Remove(profiledNode);
}
uiContext.Post(_ =>
{
var collections = new[] { ProfiledNodesLatestRun, ProfiledNodesPreviousRun, ProfiledNodesNotExecuted };

foreach (var collection in collections)
{
collection?.Remove(profiledNode);
}

targetCollection?.Add(profiledNode);
targetCollection?.Add(profiledNode);
}, null);
});
}

/// <summary>
/// Removes a node from the appropriate collection based on its state.
/// </summary>
private void RemoveNodeFromState<T>(ProfiledNodeViewModel pNode, ProfiledNodeState state, Func<ProfiledNodeState, T> getCollectionFunc) where T : ICollection<ProfiledNodeViewModel>
private void RemoveNodeFromStateCollection(ProfiledNodeViewModel pNode, ProfiledNodeState state)
{
var collection = getCollectionFunc(state);
var collection = GetObservableCollectionFromState(state);

collection?.Remove(pNode);
}

Expand Down Expand Up @@ -1516,6 +1500,17 @@ private void RefreshUIAfterReset()
UpdateTableVisibility();
}

/// <summary>
/// Refreshes the UI after group nodes are re-calculated
/// </summary>
private void RefreshGroupNodeUI()
{
ApplyCustomSorting(ProfiledNodesCollectionLatestRun);
RaisePropertyChanged(nameof(ProfiledNodesCollectionLatestRun));
ApplyCustomSorting(ProfiledNodesCollectionPreviousRun);
RaisePropertyChanged(nameof(ProfiledNodesCollectionPreviousRun));
}

#endregion

#region Dispose or setup
Expand Down

0 comments on commit 52ac350

Please sign in to comment.