Skip to content

Commit 40138f1

Browse files
committed
Add concurrency for parent packages
1 parent 4cdbea8 commit 40138f1

2 files changed

Lines changed: 223 additions & 187 deletions

File tree

src/code/FindHelper.cs

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,6 @@ internal class FindHelper
4646
// If running 'Install-PSResource Az, TestModule, NewTestModule', it will contain one parent and its dependencies.
4747
private ConcurrentDictionary<string, List<string>> _packagesFound;
4848

49-
// Creates a new instance of depPkgsFound each time FindDependencyPackages() is called.
50-
// This will eventually return the PSResourceInfo object to the main cmdlet class.
51-
private ConcurrentDictionary<string, PSResourceInfo> depPkgsFound;
52-
5349
// Contains the latest found version of a particular package.
5450
private ConcurrentDictionary<string, PSResourceInfo> _knownLatestPkgVersion;
5551

@@ -1060,13 +1056,36 @@ private IEnumerable<PSResourceInfo> SearchByNames(ServerApiCall currentServer, R
10601056
// After retrieving all packages find their dependencies
10611057
if (_includeDependencies)
10621058
{
1063-
foreach (PSResourceInfo currentPkg in parentPkgs)
1059+
// Resolving each parent package's dependency closure is independent work, so do it concurrently.
1060+
// yield return cannot be used inside Parallel.ForEach, so collect results into a thread-safe bag first.
1061+
ConcurrentBag<PSResourceInfo> dependencyPkgs = new ConcurrentBag<PSResourceInfo>();
1062+
int processorCount = Environment.ProcessorCount;
1063+
int maxDegreeOfParallelism = processorCount * 4;
1064+
if (parentPkgs.Count > processorCount)
1065+
{
1066+
Parallel.ForEach(parentPkgs, new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism }, currentPkg =>
1067+
{
1068+
foreach (PSResourceInfo pkgDep in FindDependencyPackages(currentServer, currentResponseUtil, currentPkg, repository))
1069+
{
1070+
dependencyPkgs.Add(pkgDep);
1071+
}
1072+
});
1073+
}
1074+
else
10641075
{
1065-
foreach (PSResourceInfo pkgDep in FindDependencyPackages(currentServer, currentResponseUtil, currentPkg, repository))
1076+
foreach (PSResourceInfo currentPkg in parentPkgs)
10661077
{
1067-
yield return pkgDep;
1078+
foreach (PSResourceInfo pkgDep in FindDependencyPackages(currentServer, currentResponseUtil, currentPkg, repository))
1079+
{
1080+
dependencyPkgs.Add(pkgDep);
1081+
}
10681082
}
10691083
}
1084+
1085+
foreach (PSResourceInfo pkgDep in dependencyPkgs)
1086+
{
1087+
yield return pkgDep;
1088+
}
10701089
}
10711090
}
10721091

@@ -1158,15 +1177,17 @@ private string FormatPkgVersionString(PSResourceInfo pkg)
11581177

11591178
internal IEnumerable<PSResourceInfo> FindDependencyPackages(ServerApiCall currentServer, ResponseUtil currentResponseUtil, PSResourceInfo currentPkg, PSRepositoryInfo repository)
11601179
{
1161-
depPkgsFound = new ConcurrentDictionary<string, PSResourceInfo>();
1180+
// Use a local instance so multiple parent packages can resolve their dependency closures concurrently
1181+
// without racing on shared state.
1182+
ConcurrentDictionary<string, PSResourceInfo> depPkgsFound = new ConcurrentDictionary<string, PSResourceInfo>();
11621183
_cmdletPassedIn.WriteDebug($"In FindHelper::FindDependencyPackages() - {currentPkg.Name}");
1163-
FindDependencyPackagesHelper(currentServer, currentResponseUtil, currentPkg, repository);
1184+
FindDependencyPackagesHelper(currentServer, currentResponseUtil, currentPkg, repository, depPkgsFound);
11641185

11651186
return depPkgsFound.Values.ToList();
11661187
}
11671188

11681189
// Method 2
1169-
internal void FindDependencyPackagesHelper(ServerApiCall currentServer, ResponseUtil currentResponseUtil, PSResourceInfo currentPkg, PSRepositoryInfo repository)
1190+
internal void FindDependencyPackagesHelper(ServerApiCall currentServer, ResponseUtil currentResponseUtil, PSResourceInfo currentPkg, PSRepositoryInfo repository, ConcurrentDictionary<string, PSResourceInfo> depPkgsFound)
11701191
{
11711192
ConcurrentQueue<ErrorRecord> errorMsgs = new ConcurrentQueue<ErrorRecord>();
11721193
ConcurrentQueue<string> verboseMsgs = new ConcurrentQueue<string>();
@@ -1185,15 +1206,15 @@ internal void FindDependencyPackagesHelper(ServerApiCall currentServer, Response
11851206
Parallel.ForEach(currentPkg.Dependencies, new ParallelOptions { MaxDegreeOfParallelism = maxDegreeOfParallelism }, dep =>
11861207
{
11871208
debugMsgs.Enqueue($"Finding dependency '{dep.Name}' version range '{dep.VersionRange}'");
1188-
FindDependencyPackageVersion(dep, currentServer, currentResponseUtil, currentPkg, repository, errorMsgs, warningMsgs, debugMsgs, verboseMsgs);
1209+
FindDependencyPackageVersion(dep, currentServer, currentResponseUtil, currentPkg, repository, depPkgsFound, errorMsgs, warningMsgs, debugMsgs, verboseMsgs);
11891210
});
11901211
}
11911212
else
11921213
{
11931214
foreach (var dep in currentPkg.Dependencies)
11941215
{
11951216
debugMsgs.Enqueue($"Finding dependency '{dep.Name}' version range '{dep.VersionRange}'");
1196-
FindDependencyPackageVersion(dep, currentServer, currentResponseUtil, currentPkg, repository, errorMsgs, warningMsgs, debugMsgs, verboseMsgs);
1217+
FindDependencyPackageVersion(dep, currentServer, currentResponseUtil, currentPkg, repository, depPkgsFound, errorMsgs, warningMsgs, debugMsgs, verboseMsgs);
11971218
}
11981219
}
11991220

@@ -1208,6 +1229,7 @@ private void FindDependencyPackageVersion(
12081229
ResponseUtil currentResponseUtil,
12091230
PSResourceInfo currentPkg,
12101231
PSRepositoryInfo repository,
1232+
ConcurrentDictionary<string, PSResourceInfo> depPkgsFound,
12111233
ConcurrentQueue<ErrorRecord> errorMsgs,
12121234
ConcurrentQueue<string> warningMsgs,
12131235
ConcurrentQueue<string> debugMsgs,
@@ -1228,7 +1250,7 @@ private void FindDependencyPackageVersion(
12281250
else
12291251
{
12301252
// Find this version from the server
1231-
depPkg = FindDependencyWithLowerBound(dep, currentServer, currentResponseUtil, currentPkg, repository, errorMsgs, warningMsgs, debugMsgs, verboseMsgs);
1253+
depPkg = FindDependencyWithLowerBound(dep, currentServer, currentResponseUtil, currentPkg, repository, depPkgsFound, errorMsgs, warningMsgs, debugMsgs, verboseMsgs);
12321254
}
12331255
}
12341256
else if (dep.VersionRange.HasLowerBound && dep.VersionRange.MinVersion.Equals(dep.VersionRange.MaxVersion))
@@ -1245,7 +1267,7 @@ private void FindDependencyPackageVersion(
12451267
}
12461268
else
12471269
{
1248-
depPkg = FindDependencyWithSpecificVersion(dep, currentServer, currentResponseUtil, currentPkg, repository, errorMsgs, warningMsgs, debugMsgs, verboseMsgs);
1270+
depPkg = FindDependencyWithSpecificVersion(dep, currentServer, currentResponseUtil, currentPkg, repository, depPkgsFound, errorMsgs, warningMsgs, debugMsgs, verboseMsgs);
12491271
}
12501272
}
12511273
else
@@ -1261,7 +1283,7 @@ private void FindDependencyPackageVersion(
12611283
}
12621284
else
12631285
{
1264-
depPkg = FindDependencyWithUpperBound(dep, currentServer, currentResponseUtil, currentPkg, repository, errorMsgs, warningMsgs, debugMsgs, verboseMsgs);
1286+
depPkg = FindDependencyWithUpperBound(dep, currentServer, currentResponseUtil, currentPkg, repository, depPkgsFound, errorMsgs, warningMsgs, debugMsgs, verboseMsgs);
12651287
}
12661288
}
12671289
}
@@ -1273,6 +1295,7 @@ private PSResourceInfo FindDependencyWithSpecificVersion(
12731295
ResponseUtil currentResponseUtil,
12741296
PSResourceInfo currentPkg,
12751297
PSRepositoryInfo repository,
1298+
ConcurrentDictionary<string, PSResourceInfo> depPkgsFound,
12761299
ConcurrentQueue<ErrorRecord> errorMsgs,
12771300
ConcurrentQueue<string> warningMsgs,
12781301
ConcurrentQueue<string> debugMsgs,
@@ -1351,7 +1374,7 @@ private PSResourceInfo FindDependencyWithSpecificVersion(
13511374
// This will eventually return the PSResourceInfo object to the main cmdlet class.
13521375
debugMsgs.Enqueue($"Adding'{key}' to list of dependency packages found");
13531376
depPkgsFound.TryAdd(key, depPkg);
1354-
FindDependencyPackagesHelper(currentServer, currentResponseUtil, depPkg, repository);
1377+
FindDependencyPackagesHelper(currentServer, currentResponseUtil, depPkg, repository, depPkgsFound);
13551378
}
13561379
}
13571380
}
@@ -1366,6 +1389,7 @@ private PSResourceInfo FindDependencyWithLowerBound(
13661389
ResponseUtil currentResponseUtil,
13671390
PSResourceInfo currentPkg,
13681391
PSRepositoryInfo repository,
1392+
ConcurrentDictionary<string, PSResourceInfo> depPkgsFound,
13691393
ConcurrentQueue<ErrorRecord> errorMsgs,
13701394
ConcurrentQueue<string> warningMsgs,
13711395
ConcurrentQueue<string> debugMsgs,
@@ -1419,7 +1443,7 @@ private PSResourceInfo FindDependencyWithLowerBound(
14191443
// This will eventually return the PSResourceInfo object to the main cmdlet class.
14201444
debugMsgs.Enqueue($"Adding'{key}' to list of dependency packages found");
14211445
depPkgsFound.TryAdd(key, depPkg);
1422-
FindDependencyPackagesHelper(currentServer, currentResponseUtil, depPkg, repository);
1446+
FindDependencyPackagesHelper(currentServer, currentResponseUtil, depPkg, repository, depPkgsFound);
14231447
}
14241448
}
14251449
}
@@ -1434,6 +1458,7 @@ private PSResourceInfo FindDependencyWithUpperBound(
14341458
ResponseUtil currentResponseUtil,
14351459
PSResourceInfo currentPkg,
14361460
PSRepositoryInfo repository,
1461+
ConcurrentDictionary<string, PSResourceInfo> depPkgsFound,
14371462
ConcurrentQueue<ErrorRecord> errorMsgs,
14381463
ConcurrentQueue<string> warningMsgs,
14391464
ConcurrentQueue<string> debugMsgs,
@@ -1490,7 +1515,7 @@ private PSResourceInfo FindDependencyWithUpperBound(
14901515
// This will eventually return the PSResourceInfo object to the main cmdlet class.
14911516
debugMsgs.Enqueue($"Adding'{key}' to list of dependency packages found");
14921517
depPkgsFound.TryAdd(key, depPkg);
1493-
FindDependencyPackagesHelper(currentServer, currentResponseUtil, depPkg, repository);
1518+
FindDependencyPackagesHelper(currentServer, currentResponseUtil, depPkg, repository, depPkgsFound);
14941519
}
14951520
}
14961521
}

0 commit comments

Comments
 (0)