Skip to content

Commit

Permalink
Merge pull request #657 from yuehuang010/dev/yuehuang/main_pl_load
Browse files Browse the repository at this point in the history
Improve load times by off loading property insertion to the background thread
  • Loading branch information
KirillOsenkov authored Feb 24, 2023
2 parents d510c47 + 239adfd commit 7298a8d
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 32 deletions.
8 changes: 6 additions & 2 deletions src/StructuredLogViewer/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,8 @@ private async void OpenLogFile(string filePath)
return GetErrorBuild(filePath, ex.ToString());
}
});
var openTime = stopwatch.Elapsed;
stopwatch.Restart();

if (build == null)
{
Expand All @@ -430,16 +432,18 @@ private async void OpenLogFile(string filePath)
progress.ProgressText = "Analyzing " + filePath + "...";
await QueueAnalyzeBuild(build);
}
var analyzingTime = stopwatch.Elapsed;

stopwatch.Restart();
progress.ProgressText = "Rendering tree...";
await Dispatcher.InvokeAsync(() => { }, DispatcherPriority.Loaded); // let the progress message be rendered before we block the UI again
var renderTime = stopwatch.Elapsed;

DisplayBuild(build);

var elapsed = stopwatch.Elapsed;
if (currentBuild != null)
{
currentBuild.UpdateBreadcrumb($"Load time: {elapsed}");
currentBuild.UpdateBreadcrumb($"Opening: {Math.Round(openTime.TotalSeconds, 3)}s, Analyzing: {Math.Round(analyzingTime.TotalSeconds, 3)}s");
}
}

Expand Down
111 changes: 81 additions & 30 deletions src/StructuredLogger/Construction/Construction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public class Construction
private readonly MessageProcessor messageProcessor;
private readonly StringCache stringTable;

private System.Threading.Tasks.Task bgWorker;
private BlockingCollection<System.Threading.Tasks.Task> bgJobPool;

public StringCache StringTable => stringTable;

public NamedNode EvaluationFolder => Build.EvaluationFolder;
Expand Down Expand Up @@ -66,6 +69,24 @@ public Construction()
Intern(nameof(Target));
Intern(nameof(Task));
Intern(nameof(TimedNode));

bgJobPool = new(2000);
bgWorker = new System.Threading.Tasks.Task(() =>
{
// Note: Limit MaxDegreeOfParallelism to 4 for now.
System.Threading.Tasks.Parallel.ForEach(bgJobPool.GetConsumingEnumerable(), new System.Threading.Tasks.ParallelOptions() { MaxDegreeOfParallelism = 4 }, task =>
{
task.Start();
task.Wait();
});
}, System.Threading.Tasks.TaskCreationOptions.LongRunning);
bgWorker.Start();
}

public void Shutdown()
{
bgJobPool.CompleteAdding();
bgWorker.Wait();
}

private string Intern(string text) => stringTable.Intern(text);
Expand Down Expand Up @@ -503,13 +524,22 @@ public void StatusEventRaised(object sender, BuildStatusEventArgs e)
ConstructProfilerResult(projectEvaluation, profilerResult.Value);
}

Folder globFolder = null;
if (projectEvaluationFinished.GlobalProperties != null)
{
AddGlobalProperties(projectEvaluation, projectEvaluationFinished.GlobalProperties);
globFolder = GetOrCreateGlobalPropertiesFolder(projectEvaluation, projectEvaluationFinished.GlobalProperties);
}

AddProperties(projectEvaluation, projectEvaluationFinished.Properties);
AddItems(projectEvaluation, projectEvaluationFinished.Items);
bgJobPool.Add(new System.Threading.Tasks.Task(() =>
{
if (projectEvaluationFinished.GlobalProperties != null && globFolder != null)
{
AddProperties(projectEvaluation, (IEnumerable<KeyValuePair<string, string>>)projectEvaluationFinished.GlobalProperties, projectEvaluation);
}

AddProperties(projectEvaluation, projectEvaluationFinished.Properties);
AddItems(projectEvaluation, projectEvaluationFinished.Items);
}));
}
}
}
Expand Down Expand Up @@ -826,18 +856,27 @@ public void UpdateProject(Project project, ProjectStartedEventArgs args)

project.GlobalProperties = stringTable.InternStringDictionary(args.GlobalProperties) ?? ImmutableDictionary<string, string>.Empty;

Folder globalNode = null;
if (args.GlobalProperties != null)
{
AddGlobalProperties(project, project.GlobalProperties);
globalNode = GetOrCreateGlobalPropertiesFolder(project, project.GlobalProperties);
}

if (!string.IsNullOrEmpty(args.TargetNames))
bgJobPool.Add(new System.Threading.Tasks.Task(() =>
{
AddEntryTargets(project);
}
if (args.GlobalProperties != null && globalNode != null)
{
AddProperties(globalNode, args.GlobalProperties, project);
}

AddProperties(project, args.Properties);
AddItems(project, args.Items);
if (!string.IsNullOrEmpty(args.TargetNames))
{
AddEntryTargets(project);
}

AddProperties(project, args.Properties);
AddItems(project, args.Items);
}));
}
}

Expand Down Expand Up @@ -1015,16 +1054,17 @@ public void SetTaskAssembly(string taskName, string assembly)
_taskToAssemblyMap.GetOrAdd(taskName, t => assembly);
}

private void AddGlobalProperties(TreeNode project, IEnumerable globalProperties)
private Folder GetOrCreateGlobalPropertiesFolder(TreeNode project, IEnumerable globalProperties)
{
if (globalProperties == null)
{
return;
return null;
}

var propertiesNode = project.GetOrCreateNodeWithName<Folder>(Strings.Properties, addAtBeginning: true);
var globalNode = propertiesNode.GetOrCreateNodeWithName<Folder>(Strings.Global, addAtBeginning: true);
AddProperties(globalNode, (IEnumerable<KeyValuePair<string, string>>)globalProperties, project as IProjectOrEvaluation);

return globalNode;
}

private static void AddEntryTargets(Project project)
Expand Down Expand Up @@ -1056,46 +1096,57 @@ private void AddProperties(TreeNode parent, IEnumerable<KeyValuePair<string, str
parent.EnsureChildrenCapacity(collection.Count);
}

bool tfvFound = false;
bool platformFound = false;
bool configFound = false;

foreach (var kvp in properties)
{
var property = new Property
{
Name = SoftIntern(kvp.Key),
Value = SoftIntern(kvp.Value)
};

parent.Children.Add(property); // don't use AddChild for performance
property.Parent = parent;

if (project != null)
{
if (string.Equals(kvp.Key, Strings.TargetFramework, StringComparison.OrdinalIgnoreCase))
if (!tfvFound)
{
project.TargetFramework = kvp.Value;
}
else if (string.Equals(kvp.Key, Strings.TargetFrameworks, StringComparison.OrdinalIgnoreCase))
{
// we want TargetFramework to take precedence over TargetFrameworks when both are present
if (string.IsNullOrEmpty(project.TargetFramework) && !string.IsNullOrEmpty(kvp.Value))
if (string.Equals(kvp.Key, Strings.TargetFramework, StringComparison.OrdinalIgnoreCase))
{
project.TargetFramework = kvp.Value;
tfvFound = true;
}
else if (string.Equals(kvp.Key, Strings.TargetFrameworks, StringComparison.OrdinalIgnoreCase))
{
// we want TargetFramework to take precedence over TargetFrameworks when both are present
if (string.IsNullOrEmpty(project.TargetFramework) && !string.IsNullOrEmpty(kvp.Value))
{
project.TargetFramework = kvp.Value;
tfvFound = true;
}
}
// If neither of the above are there - look for the old project system
else if (project.TargetFramework is null && string.Equals(kvp.Key, Strings.TargetFrameworkVersion, StringComparison.OrdinalIgnoreCase))
{
// Note this is untranslated, so e.g. "v4.6.2" instead of "net462" - this is intentional as it
// renders the badge for all projects, but you can still use this difference to tell what is/isn't an SDK project.
project.TargetFramework = kvp.Value;
tfvFound = true;
}
}
// If neither of the above are there - look for the old project system
else if (project.TargetFramework is null && string.Equals(kvp.Key, Strings.TargetFrameworkVersion, StringComparison.OrdinalIgnoreCase))
{
// Note this is untranslated, so e.g. "v4.6.2" instead of "net462" - this is intentional as it
// renders the badge for all projects, but you can still use this difference to tell what is/isn't an SDK project.
project.TargetFramework = kvp.Value;
}

if (string.Equals(kvp.Key, Strings.Platform, StringComparison.OrdinalIgnoreCase))
else if (!platformFound && string.Equals(kvp.Key, Strings.Platform, StringComparison.OrdinalIgnoreCase))
{
project.Platform = kvp.Value;
platformFound = true;
}

if (string.Equals(kvp.Key, Strings.Configuration, StringComparison.OrdinalIgnoreCase))
else if (!configFound && string.Equals(kvp.Key, Strings.Configuration, StringComparison.OrdinalIgnoreCase))
{
project.Configuration = kvp.Value;
configFound = true;
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/StructuredLogger/StructuredLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ private void EventSource_AnyEventRaised(object sender, BuildEventArgs e)
public override void Shutdown()
{
base.Shutdown();
construction.Shutdown();

if (projectImportsCollector != null)
{
Expand Down

0 comments on commit 7298a8d

Please sign in to comment.