cmd/coordinator: delete useScheduler knob & old pre-scheduler hacks, code, TODOs

Updates golang/go#19178

Change-Id: Id4d8b016c41f57bfaba5ee4ab046285607047493
Reviewed-on: https://go-review.googlesource.com/c/build/+/207178
Reviewed-by: Bryan C. Mills <bcmills@google.com>
diff --git a/cmd/coordinator/coordinator.go b/cmd/coordinator/coordinator.go
index 38ed98b..3915e26 100644
--- a/cmd/coordinator/coordinator.go
+++ b/cmd/coordinator/coordinator.go
@@ -451,17 +451,6 @@
 	return len(status)
 }
 
-func numCurrentBuildsOfType(typ string) (n int) {
-	statusMu.Lock()
-	defer statusMu.Unlock()
-	for rev := range status {
-		if rev.Name == typ {
-			n++
-		}
-	}
-	return
-}
-
 func isBuilding(work buildgo.BuilderRev) bool {
 	statusMu.Lock()
 	defer statusMu.Unlock()
@@ -491,9 +480,6 @@
 	if buildEnv.MaxBuilds > 0 && numCurrentBuilds() >= buildEnv.MaxBuilds {
 		return false
 	}
-	if buildConf.MaxAtOnce > 0 && numCurrentBuildsOfType(rev.Name) >= buildConf.MaxAtOnce {
-		return false
-	}
 	if buildConf.IsReverse() && !reversePool.CanBuild(buildConf.HostType) {
 		return false
 	}
@@ -879,24 +865,6 @@
 		knownToDashboard[b] = true
 	}
 
-	// Before, we just sent all the possible work to workc,
-	// which then kicks off lots of goroutines that fight over
-	// available buildlets, with the result that we run a random
-	// subset of the possible work. But really we want to run
-	// the newest possible work, so that lines at the top of the
-	// build dashboard are filled in before lines below.
-	// It's a bit hard to push that preference all the way through
-	// this code base, but we can tilt the scales a little by only
-	// sending one job to workc for each different builder
-	// on each findWork call. The findWork calls happen every
-	// 15 seconds, so we will now only kick off one build of
-	// a particular host type (for example, darwin-arm64) every
-	// 15 seconds, but they should be skewed toward new work.
-	// This depends on the build dashboard sending back the list
-	// of empty slots newest first (matching the order on the main screen).
-	// TODO: delete this code when the scheduler is on by default.
-	sent := map[string]bool{}
-
 	var goRevisions []string // revisions of repo "go", branch "master" revisions
 	seenSubrepo := make(map[string]bool)
 	for _, br := range bs.Revisions {
@@ -965,19 +933,7 @@
 				}
 			}
 
-			if useScheduler {
-				addWork(rev)
-			} else {
-				// The !sent[builder] here is a clumsy attempt at priority scheduling
-				// and probably should be replaced at some point with a better solution.
-				// See golang.org/issue/19178 and the long comment above.
-				// TODO: delete all this code and the sent map above when the
-				// useScheduler const is removed.
-				if !sent[builder] {
-					sent[builder] = true
-					addWork(rev)
-				}
-			}
+			addWork(rev)
 		}
 	}
 
@@ -1529,10 +1485,6 @@
 // buildletTimeoutOpt is a context.Value key for BuildletPool.GetBuildlet.
 type buildletTimeoutOpt struct{} // context Value key; value is time.Duration
 
-// highPriorityOpt is a context.Value key for BuildletPool.GetBuildlet.
-// If its value is true, that means the caller should be prioritized.
-type highPriorityOpt struct{} // value is bool
-
 type BuildletPool interface {
 	// GetBuildlet returns a new buildlet client.
 	//
@@ -1562,7 +1514,7 @@
 			sp := lg.CreateSpan("get_helper", fmt.Sprintf("helper %d/%d", i+1, n))
 			schedItem := *schedTmpl // copy; GetBuildlet takes ownership
 			schedItem.IsHelper = i > 0
-			bc, err := sched.GetBuildlet(ctx, lg, &schedItem)
+			bc, err := sched.GetBuildlet(ctx, &schedItem)
 			sp.Done(err)
 			if err != nil {
 				if err != context.Canceled {
@@ -1829,7 +1781,7 @@
 	st.mu.Unlock()
 
 	sp := st.CreateSpan("get_buildlet")
-	bc, err := sched.GetBuildlet(st.ctx, st, schedItem)
+	bc, err := sched.GetBuildlet(st.ctx, schedItem)
 	sp.Done(err)
 	if err != nil {
 		err = fmt.Errorf("failed to get a buildlet: %v", err)
@@ -2130,7 +2082,7 @@
 	ctx, cancel := context.WithCancel(st.ctx)
 	defer cancel()
 	sp := st.CreateSpan("get_buildlet_cross")
-	kubeBC, err := sched.GetBuildlet(ctx, st, &SchedItem{
+	kubeBC, err := sched.GetBuildlet(ctx, &SchedItem{
 		HostType:   config.CompileHostType,
 		IsTry:      st.trySet != nil,
 		BuilderRev: st.BuilderRev,
diff --git a/cmd/coordinator/remote.go b/cmd/coordinator/remote.go
index c1f30c6..2fd4697 100644
--- a/cmd/coordinator/remote.go
+++ b/cmd/coordinator/remote.go
@@ -151,22 +151,10 @@
 	// closed, the pod is destroyed.
 	// TODO: clean this up.
 
-	// Doing a release?
-	if user == "release" || user == "adg" || user == "bradfitz" {
-		ctx = context.WithValue(ctx, highPriorityOpt{}, true)
-	}
-
 	resc := make(chan *buildlet.Client)
 	errc := make(chan error)
 	go func() {
-		lgFunc := loggerFunc(func(event string, optText ...string) {
-			var extra string
-			if len(optText) > 0 {
-				extra = " " + optText[0]
-			}
-			log.Printf("creating buildlet %s for %s: %s%s", bconf.HostType, user, event, extra)
-		})
-		bc, err := sched.GetBuildlet(ctx, lgFunc, &SchedItem{
+		bc, err := sched.GetBuildlet(ctx, &SchedItem{
 			HostType: bconf.HostType,
 			IsGomote: true,
 		})
diff --git a/cmd/coordinator/reverse.go b/cmd/coordinator/reverse.go
index e776bb8..734633d 100644
--- a/cmd/coordinator/reverse.go
+++ b/cmd/coordinator/reverse.go
@@ -287,22 +287,6 @@
 	return true
 }
 
-var (
-	highPriorityBuildletMu sync.Mutex
-	highPriorityBuildlet   = make(map[string]chan *buildlet.Client)
-)
-
-func highPriChan(hostType string) chan *buildlet.Client {
-	highPriorityBuildletMu.Lock()
-	defer highPriorityBuildletMu.Unlock()
-	if c, ok := highPriorityBuildlet[hostType]; ok {
-		return c
-	}
-	c := make(chan *buildlet.Client)
-	highPriorityBuildlet[hostType] = c
-	return c
-}
-
 func (p *reverseBuildletPool) updateWaiterCounter(hostType string, delta int) {
 	p.mu.Lock()
 	defer p.mu.Unlock()
@@ -316,34 +300,21 @@
 	p.updateWaiterCounter(hostType, 1)
 	defer p.updateWaiterCounter(hostType, -1)
 	seenErrInUse := false
-	isHighPriority, _ := ctx.Value(highPriorityOpt{}).(bool)
+
 	sp := lg.CreateSpan("wait_static_builder", hostType)
 	for {
 		bc, busy := p.tryToGrab(hostType)
 		if bc != nil {
-			select {
-			case highPriChan(hostType) <- bc:
-				// Somebody else was more important.
-			default:
-				sp.Done(nil)
-				return p.cleanedBuildlet(bc, lg)
-			}
+			sp.Done(nil)
+			return p.cleanedBuildlet(bc, lg)
 		}
 		if busy > 0 && !seenErrInUse {
 			lg.LogEventTime("waiting_machine_in_use")
 			seenErrInUse = true
 		}
-		var highPri chan *buildlet.Client
-		if isHighPriority {
-			highPri = highPriChan(hostType)
-		}
 		select {
 		case <-ctx.Done():
 			return nil, sp.Done(ctx.Err())
-		case bc := <-highPri:
-			sp.Done(nil)
-			return p.cleanedBuildlet(bc, lg)
-
 		case <-time.After(10 * time.Second):
 			// As multiple goroutines can be listening for
 			// the available signal, it must be treated as
diff --git a/cmd/coordinator/sched.go b/cmd/coordinator/sched.go
index 889be6d..af316a6 100644
--- a/cmd/coordinator/sched.go
+++ b/cmd/coordinator/sched.go
@@ -21,15 +21,6 @@
 	"golang.org/x/build/internal/buildgo"
 )
 
-// useScheduler controls whether we actually use the scheduler. This
-// is temporarily false during development. Once we're happy with it
-// we'll delete this.
-//
-// If false, any GetBuildlet call to the schedule delegates directly
-// to the BuildletPool's GetBuildlet and we make a bunch of callers
-// fight over a mutex and a random one wins, like we used to do it.
-var useScheduler = true
-
 // The Scheduler prioritizes access to buidlets. It accepts requests
 // for buildlets, starts the creation of buildlets from BuildletPools,
 // and prioritizes which callers gets them first when they're ready.
@@ -333,24 +324,13 @@
 // GetBuildlet requests a buildlet with the parameters described in si.
 //
 // The provided si must be newly allocated; ownership passes to the scheduler.
-func (s *Scheduler) GetBuildlet(ctx context.Context, lg logger, si *SchedItem) (*buildlet.Client, error) {
-	// TODO: once we remove the useScheduler const, we can remove
-	// the "lg" logger parameter. We don't need to log anything
-	// during the buildlet creation process anymore because we
-	// don't know which build it'll be for. So all we can say in
-	// the logs for is "Asking for a buildlet" and "Got one",
-	// which the caller already does. I think. Verify that.
-
+func (s *Scheduler) GetBuildlet(ctx context.Context, si *SchedItem) (*buildlet.Client, error) {
 	hostConf, ok := dashboard.Hosts[si.HostType]
 	if !ok && testPoolHook == nil {
 		return nil, fmt.Errorf("invalid SchedItem.HostType %q", si.HostType)
 	}
 	pool := poolForConf(hostConf)
 
-	if !useScheduler {
-		return pool.GetBuildlet(ctx, si.HostType, lg)
-	}
-
 	si.pool = pool
 	si.s = s
 	si.requestTime = time.Now()
diff --git a/cmd/coordinator/sched_test.go b/cmd/coordinator/sched_test.go
index 25f074a..ebcab67 100644
--- a/cmd/coordinator/sched_test.go
+++ b/cmd/coordinator/sched_test.go
@@ -152,7 +152,7 @@
 func (c *getBuildletCall) start(t *testing.T, s *Scheduler) {
 	t.Logf("starting buildlet call for SchedItem=%p", c.si)
 	go func() {
-		c.gotClient, c.gotErr = s.GetBuildlet(c.ctx, discardLogger{}, c.si)
+		c.gotClient, c.gotErr = s.GetBuildlet(c.ctx, c.si)
 		close(c.done)
 	}()
 
@@ -222,8 +222,6 @@
 func (poolChan) String() string { return "testing poolChan" }
 
 func TestScheduler(t *testing.T) {
-	defer func(old bool) { useScheduler = old }(useScheduler)
-	useScheduler = true
 	defer func() { testPoolHook = nil }()
 
 	var pool poolChan // initialized per test below
diff --git a/cmd/makemac/makemac.go b/cmd/makemac/makemac.go
index b51a299..2502c3f 100644
--- a/cmd/makemac/makemac.go
+++ b/cmd/makemac/makemac.go
@@ -695,9 +695,15 @@
 // or 0 to not make anything. It gets the latest reverse buildlet
 // status from the coordinator.
 func wantedMacVersionNext(st *State, rstat *types.ReverseBuilderStatus) int {
-	// TODO: improve this logic at some point, probably when the
-	// coordinator has a proper scheduler (Issue 19178) and when
-	// the coordinator keeps 1 of each builder type ready to go.
+	// TODO: improve this logic now that the coordinator has a
+	// proper scheduler. Instead, don't create anything
+	// proactively until there's demand from it from the
+	// scheduler. (will need to add that to the coordinator's
+	// status JSON) And maybe add a streaming endpoint to the
+	// coordinator so we don't need to poll every N seconds. Or
+	// just poll every few seconds, perhaps at a lighter endpoint
+	// that only does darwin.
+	//
 	// For now just use the static configuration in
 	// dashboard/builders.go of how many are expected, which ends
 	// up in ReverseBuilderStatus.
diff --git a/dashboard/builders.go b/dashboard/builders.go
index 8e9178c..1e9f82b 100644
--- a/dashboard/builders.go
+++ b/dashboard/builders.go
@@ -774,13 +774,6 @@
 	// of repos. The callers in coordinator will need updating.
 	MinimumGoVersion types.MajorMinor
 
-	// MaxAtOnce optionally specifies a cap of how many builds of
-	// this type can run at once. Zero means unlimited. This is a
-	// temporary measure until the build scheduler
-	// (golang.org/issue/19178) is done, at which point this field
-	// should be deleted.
-	MaxAtOnce int
-
 	// SkipSnapshot, if true, means to not fetch a tarball
 	// snapshot of the world post-make.bash from the buildlet (and
 	// thus to not write it to Google Cloud Storage). This is
@@ -1354,7 +1347,6 @@
 		Name:       "freebsd-amd64-gce93",
 		HostType:   "host-freebsd-93-gce",
 		buildsRepo: disabledBuilder,
-		MaxAtOnce:  2,
 	})
 	addBuilder(BuildConfig{
 		Name:     "freebsd-amd64-10_3",
@@ -1365,7 +1357,6 @@
 		tryBot: func(repo, branch, goBranch string) bool {
 			return branch == "release-branch.go1.11" || branch == "release-branch.go1.12"
 		},
-		MaxAtOnce: 2,
 	})
 	addBuilder(BuildConfig{
 		Name:     "freebsd-amd64-10_4",
@@ -1373,8 +1364,7 @@
 		buildsRepo: func(repo, branch, goBranch string) bool {
 			return goBranch == "release-branch.go1.11" || goBranch == "release-branch.go1.12"
 		},
-		tryBot:    nil,
-		MaxAtOnce: 2,
+		tryBot: nil,
 	})
 	addBuilder(BuildConfig{
 		Name:     "freebsd-amd64-11_1",
@@ -1385,7 +1375,6 @@
 		},
 		shouldRunDistTest: fasterTrybots,
 		numTryTestHelpers: 4,
-		MaxAtOnce:         2,
 	})
 	addBuilder(BuildConfig{
 		Name:              "freebsd-amd64-11_2",
@@ -1393,7 +1382,6 @@
 		tryBot:            explicitTrySet("sys"),
 		shouldRunDistTest: fasterTrybots,
 		numTryTestHelpers: 4,
-		MaxAtOnce:         2,
 	})
 	addBuilder(BuildConfig{
 		Name:             "freebsd-amd64-12_0",
@@ -1403,7 +1391,6 @@
 
 		shouldRunDistTest: fasterTrybots,
 		numTryTestHelpers: 4,
-		MaxAtOnce:         2,
 	})
 	addBuilder(BuildConfig{
 		Name:              "freebsd-386-12_0",
@@ -1417,12 +1404,10 @@
 			return defaultBuildsRepoPolicy(repo, branch, goBranch)
 		},
 		numTryTestHelpers: 4,
-		MaxAtOnce:         2,
 	})
 	addBuilder(BuildConfig{
-		Name:      "freebsd-amd64-race",
-		HostType:  "host-freebsd-11_1",
-		MaxAtOnce: 2,
+		Name:     "freebsd-amd64-race",
+		HostType: "host-freebsd-11_1",
 	})
 	addBuilder(BuildConfig{
 		Name:     "freebsd-386-10_3",
@@ -1430,8 +1415,7 @@
 		buildsRepo: func(repo, branch, goBranch string) bool {
 			return goBranch == "release-branch.go1.11" || goBranch == "release-branch.go1.12"
 		},
-		env:       []string{"GOARCH=386", "GOHOSTARCH=386"},
-		MaxAtOnce: 2,
+		env: []string{"GOARCH=386", "GOHOSTARCH=386"},
 	})
 	addBuilder(BuildConfig{
 		Name:     "freebsd-386-10_4",
@@ -1439,8 +1423,7 @@
 		buildsRepo: func(repo, branch, goBranch string) bool {
 			return goBranch == "release-branch.go1.11" || goBranch == "release-branch.go1.12"
 		},
-		env:       []string{"GOARCH=386", "GOHOSTARCH=386"},
-		MaxAtOnce: 2,
+		env: []string{"GOARCH=386", "GOHOSTARCH=386"},
 	})
 	addBuilder(BuildConfig{
 		Name:              "freebsd-386-11_1",
@@ -1449,8 +1432,7 @@
 		buildsRepo: func(repo, branch, goBranch string) bool {
 			return goBranch == "release-branch.go1.11" || goBranch == "release-branch.go1.12"
 		},
-		env:       []string{"GOARCH=386", "GOHOSTARCH=386"},
-		MaxAtOnce: 2,
+		env: []string{"GOARCH=386", "GOHOSTARCH=386"},
 	})
 	addBuilder(BuildConfig{
 		Name:              "freebsd-386-11_2",
@@ -1462,9 +1444,8 @@
 			}
 			return defaultBuildsRepoPolicy(repo, branch, goBranch)
 		},
-		tryBot:    explicitTrySet("sys"),
-		env:       []string{"GOARCH=386", "GOHOSTARCH=386"},
-		MaxAtOnce: 2,
+		tryBot: explicitTrySet("sys"),
+		env:    []string{"GOARCH=386", "GOHOSTARCH=386"},
 	})
 	addBuilder(BuildConfig{
 		Name:              "linux-386",
@@ -1496,7 +1477,6 @@
 		env: []string{
 			"GO_DISABLE_OUTBOUND_NETWORK=1",
 		},
-		MaxAtOnce:         3,
 		numTestHelpers:    1,
 		numTryTestHelpers: 4,
 		RunBench:          true,
@@ -1504,7 +1484,6 @@
 	addBuilder(BuildConfig{
 		Name:       "linux-amd64-vmx",
 		HostType:   "host-linux-stretch-vmx",
-		MaxAtOnce:  1,
 		buildsRepo: disabledBuilder,
 	})
 
@@ -1555,10 +1534,9 @@
 	// misc-compile for ^android- and ^darwin-arm.
 
 	addBuilder(BuildConfig{
-		Name:      "linux-amd64-nocgo",
-		HostType:  "host-linux-jessie",
-		MaxAtOnce: 1,
-		Notes:     "cgo disabled",
+		Name:     "linux-amd64-nocgo",
+		HostType: "host-linux-jessie",
+		Notes:    "cgo disabled",
 		buildsRepo: func(repo, branch, goBranch string) bool {
 			switch repo {
 			case "perf":
@@ -1587,12 +1565,10 @@
 			"GO_DISABLE_OUTBOUND_NETWORK=1",
 			"GO_GCFLAGS=-N -l",
 		},
-		MaxAtOnce: 1,
 	})
 	addBuilder(BuildConfig{
 		Name:        "linux-amd64-ssacheck",
 		HostType:    "host-linux-jessie",
-		MaxAtOnce:   1,
 		buildsRepo:  onlyGo,
 		tryBot:      nil, // TODO: add a func to conditionally run this trybot if compiler dirs are touched
 		CompileOnly: true,
@@ -1609,7 +1585,6 @@
 		Name:                "linux-amd64-racecompile",
 		HostType:            "host-linux-jessie",
 		tryBot:              nil, // TODO: add a func to conditionally run this trybot if compiler dirs are touched
-		MaxAtOnce:           1,
 		CompileOnly:         true,
 		SkipSnapshot:        true,
 		StopAfterMake:       true,
@@ -1627,7 +1602,6 @@
 		HostType:          "host-linux-jessie",
 		tryBot:            defaultTrySet(),
 		buildsRepo:        defaultPlusExp,
-		MaxAtOnce:         1,
 		shouldRunDistTest: fasterTrybots,
 		numTestHelpers:    1,
 		numTryTestHelpers: 5,
@@ -1636,37 +1610,32 @@
 		},
 	})
 	addBuilder(BuildConfig{
-		Name:      "linux-386-clang",
-		HostType:  "host-linux-clang",
-		MaxAtOnce: 1,
-		Notes:     "Debian jessie + clang 3.9 instead of gcc",
-		env:       []string{"CC=/usr/bin/clang", "GOHOSTARCH=386"},
+		Name:     "linux-386-clang",
+		HostType: "host-linux-clang",
+		Notes:    "Debian jessie + clang 3.9 instead of gcc",
+		env:      []string{"CC=/usr/bin/clang", "GOHOSTARCH=386"},
 	})
 	addBuilder(BuildConfig{
-		Name:      "linux-amd64-clang",
-		HostType:  "host-linux-clang",
-		MaxAtOnce: 1,
-		Notes:     "Debian jessie + clang 3.9 instead of gcc",
-		env:       []string{"CC=/usr/bin/clang"},
+		Name:     "linux-amd64-clang",
+		HostType: "host-linux-clang",
+		Notes:    "Debian jessie + clang 3.9 instead of gcc",
+		env:      []string{"CC=/usr/bin/clang"},
 	})
 	addBuilder(BuildConfig{
-		Name:      "linux-386-sid",
-		HostType:  "host-linux-sid",
-		Notes:     "Debian sid (unstable)",
-		MaxAtOnce: 1,
-		env:       []string{"GOHOSTARCH=386"},
+		Name:     "linux-386-sid",
+		HostType: "host-linux-sid",
+		Notes:    "Debian sid (unstable)",
+		env:      []string{"GOHOSTARCH=386"},
 	})
 	addBuilder(BuildConfig{
-		Name:      "linux-amd64-sid",
-		HostType:  "host-linux-sid",
-		MaxAtOnce: 1,
-		Notes:     "Debian sid (unstable)",
+		Name:     "linux-amd64-sid",
+		HostType: "host-linux-sid",
+		Notes:    "Debian sid (unstable)",
 	})
 	addBuilder(BuildConfig{
-		Name:      "linux-amd64-fedora",
-		HostType:  "host-linux-fedora",
-		MaxAtOnce: 1,
-		Notes:     "Fedora",
+		Name:     "linux-amd64-fedora",
+		HostType: "host-linux-fedora",
+		Notes:    "Fedora",
 	})
 	addBuilder(BuildConfig{
 		Name:     "linux-amd64-androidemu",
@@ -1687,19 +1656,17 @@
 		Notes: "Runs GOOS=linux but with the Android emulator attached, for running x/mobile host tests.",
 	})
 	addBuilder(BuildConfig{
-		Name:      "linux-amd64-jessie",
-		HostType:  "host-linux-jessie",
-		MaxAtOnce: 5,
-		Notes:     "Debian Jessie. The normal 'linux-amd64' builder is stretch. We use Jessie for our release builds due to https://golang.org/issue/31293",
+		Name:     "linux-amd64-jessie",
+		HostType: "host-linux-jessie",
+		Notes:    "Debian Jessie. The normal 'linux-amd64' builder is stretch. We use Jessie for our release builds due to https://golang.org/issue/31293",
 		env: []string{
 			"GO_DISABLE_OUTBOUND_NETWORK=1",
 		},
 	})
 	addBuilder(BuildConfig{
-		Name:      "linux-amd64-longtest",
-		HostType:  "host-linux-stretch-morecpu",
-		MaxAtOnce: 1,
-		Notes:     "Debian Stretch with go test -short=false",
+		Name:     "linux-amd64-longtest",
+		HostType: "host-linux-stretch-morecpu",
+		Notes:    "Debian Stretch with go test -short=false",
 		buildsRepo: func(repo, branch, goBranch string) bool {
 			return repo == "go" || (branch == "master" && goBranch == "master")
 		},
@@ -1710,10 +1677,9 @@
 		},
 	})
 	addBuilder(BuildConfig{
-		Name:      "linux-386-longtest",
-		HostType:  "host-linux-stretch-morecpu",
-		MaxAtOnce: 1,
-		Notes:     "Debian Stretch with go test -short=false; to get 32-bit coverage",
+		Name:     "linux-386-longtest",
+		HostType: "host-linux-stretch-morecpu",
+		Notes:    "Debian Stretch with go test -short=false; to get 32-bit coverage",
 		buildsRepo: func(repo, branch, goBranch string) bool {
 			return repo == "go" || (branch == "master" && goBranch == "master")
 		},
@@ -1794,7 +1760,6 @@
 			// nacl support is removed in Go 1.14.
 			return repo == "go" && !atLeastGo1(goBranch, 14) && !strings.HasPrefix(goBranch, "dev.")
 		},
-		MaxAtOnce:         2,
 		numTryTestHelpers: 3,
 		env:               []string{"GOOS=nacl", "GOARCH=386", "GOHOSTOS=linux", "GOHOSTARCH=amd64"},
 	})
@@ -1806,7 +1771,6 @@
 			return repo == "go" && !atLeastGo1(goBranch, 14) && !strings.HasPrefix(goBranch, "dev.")
 		},
 		tryBot:            explicitTrySet("go"),
-		MaxAtOnce:         2,
 		numTryTestHelpers: 3,
 		env:               []string{"GOOS=nacl", "GOARCH=amd64p32", "GOHOSTOS=linux", "GOHOSTARCH=amd64"},
 	})
@@ -1850,7 +1814,6 @@
 		HostType:          "host-openbsd-amd64-60",
 		shouldRunDistTest: noTestDir,
 		buildsRepo:        disabledBuilder,
-		MaxAtOnce:         1,
 		numTestHelpers:    2,
 		numTryTestHelpers: 5,
 	})
@@ -1859,7 +1822,6 @@
 		HostType:          "host-openbsd-386-60",
 		shouldRunDistTest: noTestDir,
 		buildsRepo:        disabledBuilder,
-		MaxAtOnce:         1,
 		env: []string{
 			// cmd/go takes ~192 seconds on openbsd-386
 			// now, which is over the 180 second default
@@ -1872,7 +1834,6 @@
 		Name:              "openbsd-386-62",
 		HostType:          "host-openbsd-386-62",
 		shouldRunDistTest: noTestDir,
-		MaxAtOnce:         1,
 		env: []string{
 			// cmd/go takes ~192 seconds on openbsd-386
 			// now, which is over the 180 second default
@@ -1888,7 +1849,6 @@
 		tryBot:            nil,
 		numTestHelpers:    0,
 		numTryTestHelpers: 5,
-		MaxAtOnce:         1,
 	})
 	addBuilder(BuildConfig{
 		Name:              "openbsd-amd64-64",
@@ -1898,20 +1858,17 @@
 		tryBot:            defaultTrySet(),
 		numTestHelpers:    0,
 		numTryTestHelpers: 5,
-		MaxAtOnce:         1,
 	})
 	addBuilder(BuildConfig{
 		Name:              "openbsd-386-64",
 		HostType:          "host-openbsd-386-64",
 		tryBot:            explicitTrySet("sys"),
 		shouldRunDistTest: noTestDir,
-		MaxAtOnce:         1,
 	})
 	addBuilder(BuildConfig{
 		Name:              "openbsd-arm-jsing",
 		HostType:          "host-openbsd-arm-joelsing",
 		shouldRunDistTest: noTestDir,
-		MaxAtOnce:         1,
 		tryBot:            nil,
 		env: []string{
 			// The machine is slow.
@@ -1932,14 +1889,12 @@
 		Name:              "netbsd-amd64-8_0",
 		HostType:          "host-netbsd-amd64-8_0",
 		shouldRunDistTest: netBSDDistTestPolicy,
-		MaxAtOnce:         1,
 		tryBot:            explicitTrySet("sys"),
 	})
 	addBuilder(BuildConfig{
 		Name:              "netbsd-386-8_0",
 		HostType:          "host-netbsd-386-8_0",
 		shouldRunDistTest: netBSDDistTestPolicy,
-		MaxAtOnce:         1,
 		// This builder currently hangs in the runtime tests; Issue 31726.
 		buildsRepo: disabledBuilder,
 	})
@@ -1947,7 +1902,6 @@
 		Name:              "netbsd-arm-bsiegert",
 		HostType:          "host-netbsd-arm-bsiegert",
 		shouldRunDistTest: netBSDDistTestPolicy,
-		MaxAtOnce:         1,
 		tryBot:            nil,
 		env: []string{
 			// The machine is slow.
@@ -1957,7 +1911,6 @@
 	addBuilder(BuildConfig{
 		Name:           "plan9-386",
 		HostType:       "host-plan9-386-gce",
-		MaxAtOnce:      2,
 		numTestHelpers: 1,
 		tryOnly:        true, // disable it for now; Issue 31261, Issue 29801
 		shouldRunDistTest: func(distTestName string, isTry bool) bool {
@@ -1991,7 +1944,6 @@
 		buildsRepo:        defaultPlusExp,
 		shouldRunDistTest: fasterTrybots,
 		env:               []string{"GOARCH=386", "GOHOSTARCH=386"},
-		MaxAtOnce:         2,
 		tryBot:            defaultTrySet(),
 		numTryTestHelpers: 4,
 	})
@@ -2009,7 +1961,6 @@
 			// up:
 			"GO_TEST_TIMEOUT_SCALE=2",
 		},
-		MaxAtOnce: 2,
 	})
 	addBuilder(BuildConfig{
 		Name:              "windows-amd64-2016",
@@ -2029,10 +1980,9 @@
 		numTryTestHelpers: 5,
 	})
 	addBuilder(BuildConfig{
-		Name:      "windows-amd64-longtest",
-		HostType:  "host-windows-amd64-2016",
-		MaxAtOnce: 1,
-		Notes:     "Windows Server 2016 with go test -short=false",
+		Name:     "windows-amd64-longtest",
+		HostType: "host-windows-amd64-2016",
+		Notes:    "Windows Server 2016 with go test -short=false",
 		buildsRepo: func(repo, branch, goBranch string) bool {
 			if !defaultPlusExp(repo, branch, goBranch) {
 				return false
@@ -2099,8 +2049,7 @@
 		buildsRepo: func(repo, branch, goBranch string) bool {
 			return repo == "go" && atLeastGo1(branch, 13)
 		},
-		MaxAtOnce: 1,
-		env:       []string{"GOARCH=386", "GOHOSTARCH=386"},
+		env: []string{"GOARCH=386", "GOHOSTARCH=386"},
 	})
 	addBuilder(BuildConfig{
 		Name:              "darwin-amd64-10_12",
@@ -2116,7 +2065,6 @@
 	addBuilder(BuildConfig{
 		Name:              "darwin-amd64-nocgo",
 		HostType:          "host-darwin-10_14",
-		MaxAtOnce:         1,
 		shouldRunDistTest: noTestDir,
 		env:               []string{"CGO_ENABLED=0"},
 	})
diff --git a/maintner/maintnerd/maintapi/api.go b/maintner/maintnerd/maintapi/api.go
index f4fb6f7..662a73a 100644
--- a/maintner/maintnerd/maintapi/api.go
+++ b/maintner/maintnerd/maintapi/api.go
@@ -282,14 +282,13 @@
 		res.Waiting = append(res.Waiting, work)
 	}
 
-	// Sort in some stable order.
-	//
-	// TODO: better would be sorting by time the trybot was
-	// requested, or the time of the CL. But we don't return that
-	// (yet?) because the coordinator has never needed it
-	// historically. But if we do a proper scheduler (Issue
-	// 19178), perhaps it would be good data to have in the
-	// coordinator.
+	// Sort in some stable order. The coordinator's scheduler
+	// currently only uses the time the trybot run was requested,
+	// and not the commit time yet, but if two trybot runs are
+	// requested within the coordinator's poll interval, the
+	// earlier commit being first seems fair enough. Plus it's
+	// nice for interactive maintq queries to not have random
+	// orders.
 	sort.Slice(res.Waiting, func(i, j int) bool {
 		return res.Waiting[i].Commit < res.Waiting[j].Commit
 	})