Cap concurrency when parsing blueprint files
Darwin has a default limit of 256 open files per process. Parsing
too many blueprint files in parallel can hit the limit. Cap the
concurrency at 200.
Test: manual testing with limit set to 32
Change-Id: Ic64d21d2c0ffd7c86bf3f02fb51216ee5684a80c
diff --git a/context.go b/context.go
index 6793ac3..9dd68b4 100644
--- a/context.go
+++ b/context.go
@@ -719,10 +719,14 @@
// Number of outstanding goroutines to wait for
count := 0
- startParseBlueprintsFile := func(filename string, scope *parser.Scope) {
+ startParseBlueprintsFile := func(blueprint stringAndScope) {
+ if blueprintsSet[blueprint.string] {
+ return
+ }
+ blueprintsSet[blueprint.string] = true
count++
go func() {
- c.parseBlueprintsFile(filename, scope, rootDir,
+ c.parseBlueprintsFile(blueprint.string, blueprint.Scope, rootDir,
errsCh, fileCh, blueprintsCh, depsCh)
doneCh <- struct{}{}
}()
@@ -730,7 +734,9 @@
tooManyErrors := false
- startParseBlueprintsFile(rootFile, nil)
+ startParseBlueprintsFile(stringAndScope{rootFile, nil})
+
+ var pending []stringAndScope
loop:
for {
@@ -749,14 +755,19 @@
if tooManyErrors {
continue
}
- if blueprintsSet[blueprint.string] {
+ // Limit concurrent calls to parseBlueprintFiles to 200
+ // Darwin has a default limit of 256 open files
+ if count >= 200 {
+ pending = append(pending, blueprint)
continue
}
-
- blueprintsSet[blueprint.string] = true
- startParseBlueprintsFile(blueprint.string, blueprint.Scope)
+ startParseBlueprintsFile(blueprint)
case <-doneCh:
count--
+ if len(pending) > 0 {
+ startParseBlueprintsFile(pending[len(pending)-1])
+ pending = pending[:len(pending)-1]
+ }
if count == 0 {
break loop
}