Skip to content

Commit

Permalink
sandbox: reduce container starvation
Browse files Browse the repository at this point in the history
Creating a container in the sandbox takes 500ms to 1s. The sandbox was
creating containers serially, but serving requests in parallel. This
means that we can be starved for workers with a trivial number of
requests.

In addition, the sandbox in production is not CPU bound, meaning we
probably have room to do some extra work while serving a request.

This CL introduces a worker pool to create containers. It also changes
the readyContainer chan to unbuffered to avoid having twice as many
containers as we expect while idle (the container waiting to be sent
plus those already in the channel's buffer).

Updates golang/go#25224
Updates golang/go#38530

Change-Id: I0e535cf65409c3dbf32329577a1c0687c2614a0d
Reviewed-on: https://go-review.googlesource.com/c/playground/+/229981
Run-TryBot: Alexander Rakoczy <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: Carlos Amedee <[email protected]>
  • Loading branch information
toothrot committed Apr 27, 2020
1 parent 560694f commit 195e12f
Showing 1 changed file with 8 additions and 2 deletions.
10 changes: 8 additions & 2 deletions sandbox/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func main() {
}
log.Printf("Go playground sandbox starting.")

readyContainer = make(chan *Container, *numWorkers)
readyContainer = make(chan *Container)
runSem = make(chan struct{}, *numWorkers)
go handleSignals()

Expand Down Expand Up @@ -148,7 +148,7 @@ func main() {
mux.Handle("/", ochttp.WithRouteTag(http.HandlerFunc(rootHandler), "/"))
mux.Handle("/run", ochttp.WithRouteTag(http.HandlerFunc(runHandler), "/run"))

go makeWorkers()
makeWorkers()
go internal.PeriodicallyDo(context.Background(), 10*time.Second, func(ctx context.Context, _ time.Time) {
countDockerContainers(ctx)
})
Expand Down Expand Up @@ -364,6 +364,12 @@ func runInGvisor() {
func makeWorkers() {
ctx := context.Background()
stats.Record(ctx, mMaxContainers.M(int64(*numWorkers)))
for i := 0; i < *numWorkers; i++ {
go workerLoop(ctx)
}
}

func workerLoop(ctx context.Context) {
for {
c, err := startContainer(ctx)
if err != nil {
Expand Down

0 comments on commit 195e12f

Please sign in to comment.