Skip to content

Commit 2ff5fbf

Browse files
rscgopherbot
authored andcommitted
cmd/compile: limit goroutine count to parallelism
When the compiler crashes, it is not uncommon to see many hundreds of goroutines all blocked waiting their turn to be one of the nWorkers goroutines that is allowed to run. All these goroutine stacks are not a terribly efficient use of memory, and they also make the crash dumps hard to read. Introduce a manager goroutine to hand out work to at most nWorker goroutines, maintaining pending work in a local slice, rather than having all those blocked goroutines hanging around waiting to run. Change-Id: I46cb4e1afd6392805f359e14554ebc17d538bcba Reviewed-on: https://go-review.googlesource.com/c/go/+/431956 Reviewed-by: Cuong Manh Le <[email protected]> Reviewed-by: Cherry Mui <[email protected]> Run-TryBot: Russ Cox <[email protected]> Auto-Submit: Russ Cox <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 9861e8b commit 2ff5fbf

File tree

1 file changed

+31
-13
lines changed

1 file changed

+31
-13
lines changed

src/cmd/compile/internal/gc/compile.go

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -126,20 +126,38 @@ func compileFunctions() {
126126
}
127127

128128
if nWorkers := base.Flag.LowerC; nWorkers > 1 {
129-
// For concurrent builds, we create a goroutine per task, but
130-
// require them to hold a unique worker ID while performing work
131-
// to limit parallelism.
132-
workerIDs := make(chan int, nWorkers)
133-
for i := 0; i < nWorkers; i++ {
134-
workerIDs <- i
135-
}
136-
129+
// For concurrent builds, we allow the work queue
130+
// to grow arbitrarily large, but only nWorkers work items
131+
// can be running concurrently.
132+
workq := make(chan func(int))
133+
done := make(chan int)
134+
go func() {
135+
ids := make([]int, nWorkers)
136+
for i := range ids {
137+
ids[i] = i
138+
}
139+
var pending []func(int)
140+
for {
141+
select {
142+
case work := <-workq:
143+
pending = append(pending, work)
144+
case id := <-done:
145+
ids = append(ids, id)
146+
}
147+
for len(pending) > 0 && len(ids) > 0 {
148+
work := pending[len(pending)-1]
149+
id := ids[len(ids)-1]
150+
pending = pending[:len(pending)-1]
151+
ids = ids[:len(ids)-1]
152+
go func() {
153+
work(id)
154+
done <- id
155+
}()
156+
}
157+
}
158+
}()
137159
queue = func(work func(int)) {
138-
go func() {
139-
worker := <-workerIDs
140-
work(worker)
141-
workerIDs <- worker
142-
}()
160+
workq <- work
143161
}
144162
}
145163

0 commit comments

Comments
 (0)