in sweet/benchmarks/gvisor/http_server.go [90:206]
func (b httpServer) run(cfg *config, out io.Writer) (err error) {
procs := runtime.GOMAXPROCS(-1)
clientProcs := procs / 4
if clientProcs == 0 {
clientProcs = 1
}
serverProcs := procs - clientProcs
if serverProcs == 0 {
serverProcs = 1
}
runtime.GOMAXPROCS(clientProcs)
defer runtime.GOMAXPROCS(procs)
clients := clientProcs
baseSrvCmd := cfg.runscCmd(
"-rootless", "do", "-ip", ip,
workloadsPath(cfg.assetsDir, "http"),
"-host", ip,
"-port", port,
"-assets", filepath.Join(cfg.assetsDir, "http", "assets"),
"-procs", strconv.Itoa(serverProcs),
)
baseSrvCmd.Stdout = out
baseSrvCmd.Stderr = out
srvCmd, err := cgroups.WrapCommand(baseSrvCmd, "test-http-server.scope")
if err != nil {
return err
}
ctx := context.Background()
defer func() {
if r := srvCmd.Process.Signal(os.Interrupt); r != nil {
if err != nil {
fmt.Fprintf(os.Stderr, "failed to force shut down server: %v\n", r)
} else {
err = r
}
}
if r := srvCmd.Wait(); r != nil {
ee, ok := r.(*exec.ExitError)
if ok {
status := ee.ProcessState.Sys().(syscall.WaitStatus)
if status.Signaled() && status.Signal() == os.Interrupt {
return
}
}
if err != nil {
fmt.Fprintf(os.Stderr, "warning: failed to wait for server: %v\n", r)
return
}
err = r
return
}
}()
err = driver.RunBenchmark(b.name()+"Startup", func(d *driver.B) error {
if err := srvCmd.Start(); err != nil {
return err
}
// Poll until the server is ready to serve, up to a maximum in case of a bug.
const timeout = 30 * time.Second
start := time.Now()
for time.Now().Sub(start) < timeout {
resp, err := httpGet(ctx, host)
if err == nil {
resp.Body.Close()
break
}
}
if time.Now().Sub(start) >= timeout {
return fmt.Errorf("server startup timed out")
}
return nil
}, driver.DoTime(true))
workers := make([]pool.Worker, 0, clients)
for i := 0; i < clients; i++ {
workers = append(workers, newWorker())
}
// Run the benchmark for b.duration.
ctx, cancel := context.WithTimeout(ctx, b.duration)
defer cancel()
p := pool.New(ctx, workers)
return driver.RunBenchmark(b.name(), func(d *driver.B) error {
if err := p.Run(); err != nil {
return err
}
d.StopTimer()
// Test is done, bring all latency measurements together.
latencies := make([]time.Duration, 0, len(workers)*100000)
for _, w := range workers {
latencies = append(latencies, w.(*worker).lat...)
}
sort.Slice(latencies, func(i, j int) bool {
return latencies[i] < latencies[j]
})
// Sort and report percentiles.
p50 := latencies[len(latencies)*50/100]
p90 := latencies[len(latencies)*90/100]
p99 := latencies[len(latencies)*99/100]
d.Report("p50-latency-ns", uint64(p50))
d.Report("p90-latency-ns", uint64(p90))
d.Report("p99-latency-ns", uint64(p99))
// Report throughput.
lengthS := float64(b.duration) / float64(time.Second)
reqsPerSec := float64(len(latencies)) / lengthS
d.Report("ops/s", uint64(reqsPerSec))
// Report the average request latency.
d.Ops(len(latencies))
d.Report(driver.StatTime, uint64((int(b.duration)*clients)/len(latencies)))
return nil
}, driver.DoTime(true), driver.DoAvgRSS(srvCmd.RSSFunc()))
}