Skip to content
This repository was archived by the owner on Sep 30, 2023. It is now read-only.

Commit cbe1406

Browse files
degtepkunga
authored andcommitted
Ускорение build-deps (#45)
* faster build-deps with caching * another fix for no nuget restore for root while build-deps * split test
1 parent 19fce5b commit cbe1406

File tree

9 files changed

+73
-28
lines changed

9 files changed

+73
-28
lines changed

Commands/Build.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
using System.Collections.Generic;
1+
using System.Collections.Generic;
22
using System.IO;
3+
using System.Threading.Tasks;
34
using Common;
45

56
namespace Commands
@@ -52,12 +53,15 @@ protected override int Execute()
5253
return -1;
5354
}
5455

56+
var builder = new ModuleBuilder(Log, buildSettings);
57+
var builderInitTask = Task.Run(() => builder.Init());
58+
5559
new BuildPreparer(Log).GetModulesOrder(moduleName, configuration, out topSortedDeps, out modulesToUpdate, out currentCommitHases);
5660

5761
var builtStorage = BuiltInfoStorage.Deserialize();
5862
builtStorage.RemoveBuildInfo(moduleName);
5963

60-
var builder = new ModuleBuilder(Log, buildSettings);
64+
builderInitTask.Wait();
6165
var module = new Dep(moduleName, null, configuration);
6266

6367
BuildDeps.TryNugetRestore(new List<Dep> {module}, builder);

Commands/BuildDeps.cs

+7-6
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,25 @@ protected override int Execute()
4545
var moduleName = Path.GetFileName(cwd);
4646

4747
configuration = string.IsNullOrEmpty(configuration) ? "full-build" : configuration;
48-
4948
List<Dep> modulesToBuild;
5049
List<Dep> topSortedDeps;
5150
Dictionary<string, string> currentCommitHases;
52-
51+
var builder = new ModuleBuilder(Log, buildSettings);
52+
var builderInitTask = Task.Run(() => builder.Init());
5353
new BuildPreparer(Log).GetModulesOrder(moduleName, configuration ?? "full-build", out topSortedDeps, out modulesToBuild, out currentCommitHases);
54+
if (modulesToBuild.Count > 0 && modulesToBuild[modulesToBuild.Count - 1].Name == moduleName)
55+
{
56+
modulesToBuild.RemoveAt(modulesToBuild.Count - 1); //remove root
57+
}
5458
if (rebuild)
5559
modulesToBuild = topSortedDeps;
5660

5761
var builtStorage = BuiltInfoStorage.Deserialize();
5862
foreach (var dep in modulesToBuild)
5963
builtStorage.RemoveBuildInfo(dep.Name);
60-
61-
var builder = new ModuleBuilder(Log, buildSettings);
6264

65+
builderInitTask.Wait();
6366
TryNugetRestore(modulesToBuild, builder);
64-
6567
int built = 1;
6668
for (var i = 0; i < topSortedDeps.Count - 1; i++)
6769
{
@@ -92,7 +94,6 @@ protected override int Execute()
9294
built++;
9395
}
9496
builtStorage.Save();
95-
9697
Log.Debug("msbuild time: " + ModuleBuilder.TotalMsbuildTime);
9798
return 0;
9899
}

Commands/PackCommand.cs

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ protected override int Execute()
4444
{
4545
XmlDocumentHelper.Save(patchedDocument, projectPath, "\n");
4646
var moduleBuilder = new ModuleBuilder(Log, buildSettings);
47+
moduleBuilder.Init();
4748
ConsoleWriter.WriteInfo("start pack");
4849
moduleBuilder.DotnetPack(modulePath, projectPath, buildData?.Configuration ?? "Release");
4950
}

Common/BuildPreparer.cs

+20-11
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,14 @@ public void GetModulesOrder(string moduleName, string configuration, out List<De
2020
{
2121
log.Debug("Building configurations graph");
2222
ConsoleWriter.WriteProgress("Building configurations graph");
23-
2423
var configsGraph = BuildConfigsGraph(moduleName, configuration);
2524
configsGraph = EraseExtraChildren(configsGraph);
2625
topSortedVertices = GetTopologicallySortedGraph(configsGraph, moduleName, configuration);
27-
26+
2827
log.Debug("Getting current commit hashes");
2928
ConsoleWriter.WriteProgress("Getting current commit hashes");
3029
currentCommitHashes = GetCurrentCommitHashes(configsGraph);
3130
updatedModules = BuiltInfoStorage.Deserialize().GetUpdatedModules(topSortedVertices, currentCommitHashes);
32-
3331
ConsoleWriter.ResetProgress();
3432
}
3533

@@ -149,22 +147,33 @@ public static Dictionary<Dep, List<Dep>> BuildConfigsGraph(string moduleName, st
149147
return graph;
150148
}
151149

152-
private static void Dfs(Dep dep, Dictionary<Dep, List<Dep>> graph, HashSet<Dep> visitedConfigurations)
150+
private static readonly Dictionary<string, bool> DepConfigurationExistsCache = new Dictionary<string, bool>();
151+
private static void CheckAndUpdateDepConfiguration(Dep dep)
153152
{
154153
dep.UpdateConfigurationIfNull();
155-
156-
if (Yaml.Exists(dep.Name) && !Yaml.ConfigurationParser(dep.Name).ConfigurationExists(dep.Configuration))
154+
var key = dep.ToString();
155+
if (!DepConfigurationExistsCache.ContainsKey(key))
156+
{
157+
if (!Directory.Exists(Path.Combine(Helper.CurrentWorkspace, dep.Name)))
158+
{
159+
throw new CementBuildException("Failed to find module '" + dep.Name + "'");
160+
}
161+
DepConfigurationExistsCache[key] = !Yaml.Exists(dep.Name) ||
162+
Yaml.ConfigurationParser(dep.Name).ConfigurationExists(dep.Configuration);
163+
}
164+
if (!DepConfigurationExistsCache[key])
157165
{
158-
ConsoleWriter.WriteWarning($"Configuration '{dep.Configuration}' was not found in {dep.Name}. Will take full-build config");
166+
ConsoleWriter.WriteWarning(
167+
$"Configuration '{dep.Configuration}' was not found in {dep.Name}. Will take full-build config");
159168
dep.Configuration = "full-build";
160169
}
170+
}
161171

172+
private static void Dfs(Dep dep, Dictionary<Dep, List<Dep>> graph, HashSet<Dep> visitedConfigurations)
173+
{
174+
CheckAndUpdateDepConfiguration(dep);
162175
visitedConfigurations.Add(dep);
163176
graph[dep] = new List<Dep>();
164-
if (!Directory.Exists(Path.Combine(Helper.CurrentWorkspace, dep.Name)))
165-
{
166-
throw new CementBuildException("Failed to find module '" + dep.Name + "'");
167-
}
168177
var currentDeps = new DepsParser(Path.Combine(Helper.CurrentWorkspace, dep.Name)).Get(dep.Configuration).Deps ?? new List<Dep>();
169178
currentDeps = currentDeps.Select(d => new Dep(d.Name, null, d.Configuration)).ToList();
170179
foreach (var d in currentDeps)

Common/BuiltInfoStorage.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.IO;
44
using System.Linq;
@@ -73,7 +73,7 @@ public void Save()
7373

7474
public List<Dep> GetUpdatedModules(List<Dep> modules, Dictionary<string, string> currentCommitHashes)
7575
{
76-
return modules.Where(module => IsModuleUpdate(currentCommitHashes, module)).ToList();
76+
return modules.AsParallel().Where(module => IsModuleUpdate(currentCommitHashes, module)).ToList();
7777
}
7878

7979
private bool IsModuleUpdate(Dictionary<string, string> currentCommitHashes, Dep module)

Common/Dep.cs

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.IO;
44
using System.Linq;
@@ -13,6 +13,7 @@ public class Dep : IEquatable<Dep>
1313
public string Treeish { get; set; }
1414
public string Configuration { get; set; }
1515
public bool NeedSrc { get; set; }
16+
static readonly Dictionary<string, string> DepDefaultConfigurationCache = new Dictionary<string, string>();
1617

1718
public Dep(string name, string treeish = null, string configuration = null)
1819
{
@@ -53,16 +54,23 @@ public Dep(string fromYamlString)
5354
Configuration = null;
5455
}
5556

57+
5658
public void UpdateConfigurationIfNull()
5759
{
5860
UpdateConfigurationIfNull(Helper.CurrentWorkspace);
5961
}
6062

6163
public void UpdateConfigurationIfNull(string workspace)
6264
{
63-
Configuration = Configuration ??
64-
new ConfigurationParser(new FileInfo(Path.Combine(workspace, Name)))
65-
.GetDefaultConfigurationName();
65+
if (!string.IsNullOrEmpty(Configuration)) return;
66+
var path = Path.Combine(workspace, Name);
67+
if (!DepDefaultConfigurationCache.ContainsKey(path))
68+
{
69+
DepDefaultConfigurationCache[path] =
70+
new ConfigurationParser(new FileInfo(Path.Combine(workspace, Name)))
71+
.GetDefaultConfigurationName();
72+
}
73+
Configuration = DepDefaultConfigurationCache[path];
6674
}
6775

6876
private string UnEscapeBadChars(string str)

Common/ModuleBuilder.cs

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ public ModuleBuilder(ILog log, BuildSettings buildSettings)
1818
{
1919
this.log = log;
2020
this.buildSettings = buildSettings;
21+
}
22+
23+
public void Init()
24+
{
2125
VsDevHelper.ReplaceVariablesToVs();
2226
}
2327

Tests/BuildTests/TestBuildDepsOrder.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.Collections.Generic;
1+
using System.Collections.Generic;
22
using System.IO;
33
using System.Linq;
44
using Common;

Tests/CommandsTests/TestGet.cs

+20-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System.Collections.Generic;
1+
using System.Collections.Generic;
22
using System.IO;
33
using Common;
44
using Common.YamlParsers;
@@ -634,7 +634,7 @@ public void TestDoesNotThrowWhenDefaultTreeishAndNotDefaultTreeish2()
634634
}
635635

636636
[Test]
637-
public void TestGetDepsWithBranches()
637+
public void TestGetDepsWithBranchesFullBuild()
638638
{
639639
using (var env = new TestEnvironment())
640640
{
@@ -657,12 +657,30 @@ public void TestGetDepsWithBranches()
657657
env.Get("A");
658658
Assert.IsTrue(Directory.Exists(Path.Combine(dir, "C")));
659659
Assert.AreEqual("branch1", new GitRepository("C", dir, Log).CurrentLocalTreeish().Value);
660+
}
661+
}
662+
663+
[Test]
664+
public void TestGetDepsWithBranchesClientBuild()
665+
{
666+
using (var env = new TestEnvironment())
667+
{
668+
var dir = env.WorkingDirectory.Path;
660669

670+
env.CreateRepo("A", new Dictionary<string, DepsContent>
671+
{
672+
{"full-build", new DepsContent(null, new List<Dep> {new Dep("B@master")})}
673+
});
661674
env.CreateRepo("B", new Dictionary<string, DepsContent>
662675
{
663676
{"full-build", new DepsContent(null, new List<Dep> {new Dep("C@branch1")})},
664677
{"client *default", new DepsContent(null, new List<Dep> {new Dep("C@branch2")})}
665678
});
679+
env.CreateRepo("C", new Dictionary<string, DepsContent>
680+
{
681+
{"full-build", new DepsContent(null, new List<Dep>())}
682+
}, new[] { "master", "branch1", "branch2" });
683+
666684
env.Get("A");
667685
Assert.IsTrue(Directory.Exists(Path.Combine(dir, "C")));
668686
Assert.AreEqual("branch2", new GitRepository("C", dir, Log).CurrentLocalTreeish().Value);

0 commit comments

Comments
 (0)