carlos / todomvc-bakeoff Public

Clone
git clone https://amadan.net/carlos/todomvc-bakeoff

Plain git — no account needed to clone.

Download

Download this file

1package bakeoff
2
3import (
4 "crypto/tls"
5 "io"
6 "net/http"
7 "net/http/httptrace"
8 "sort"
9 "time"
10)
11
12// Stats summarises a set of samples in milliseconds.
13type Stats struct {
14 N int
15 P50, P95, P99, Min, Max float64
16}
17
18func summarise(ms []float64) Stats {
19 sort.Float64s(ms)
20 pick := func(p float64) float64 { return ms[int(p*float64(len(ms)-1)+0.5)] }
21 return Stats{N: len(ms), P50: pick(0.5), P95: pick(0.95), P99: pick(0.99), Min: ms[0], Max: ms[len(ms)-1]}
22}
23
24// timeToFirstByte makes one GET on a fresh connection (DNS, TCP and TLS
25// included, as a new visitor would pay them) and returns the milliseconds
26// until the first response byte.
27func (s *Session) timeToFirstByte(path string) (float64, error) {
28 tr := &http.Transport{DisableKeepAlives: true, TLSClientConfig: &tls.Config{}}
29 defer tr.CloseIdleConnections()
30 c := &http.Client{Transport: tr, Jar: s.Client.Jar, CheckRedirect: s.Client.CheckRedirect, Timeout: s.Client.Timeout}
31 var first time.Time
32 req, _ := http.NewRequest("GET", s.Base.String()+path, nil)
33 req = req.WithContext(httptrace.WithClientTrace(req.Context(), &httptrace.ClientTrace{
34 GotFirstResponseByte: func() { first = time.Now() },
35 }))
36 start := time.Now()
37 res, err := c.Do(req)
38 if err != nil {
39 return 0, err
40 }
41 io.Copy(io.Discard, res.Body)
42 res.Body.Close()
43 return float64(first.Sub(start).Microseconds()) / 1000, nil
44}
45
46// MeasureTTFB discards warmup requests, then times n.
47func MeasureTTFB(s *Session, path string, warmup, n int) (Stats, error) {
48 for i := 0; i < warmup; i++ {
49 if _, err := s.timeToFirstByte(path); err != nil {
50 return Stats{}, err
51 }
52 }
53 ms := make([]float64, 0, n)
54 for i := 0; i < n; i++ {
55 v, err := s.timeToFirstByte(path)
56 if err != nil {
57 return Stats{}, err
58 }
59 ms = append(ms, v)
60 }
61 return summarise(ms), nil
62}
63