package main

import (
	"fmt"
	"io"
	"math"
	"net/http"
	"net/http/httptest"
	"os"
	"slices"
	"time"
)

func measure(name string, fn func() error) {
	const n = 200
	for range 10 {
		if err := fn(); err != nil {
			panic(err)
		}
	}
	ds := make([]float64, n)
	for i := range ds {
		start := time.Now()
		if err := fn(); err != nil {
			panic(err)
		}
		ds[i] = float64(time.Since(start).Nanoseconds()) / 1000
	}
	slices.Sort(ds)
	q := func(p float64) float64 { return ds[int(math.Ceil(float64(n)*p))-1] }
	fmt.Printf("%s n=%d p50=%.2f p95=%.2f p99=%.2f us\n", name, n, q(.5), q(.95), q(.99))
}
func main() {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, _ = io.WriteString(w, "ok") }))
	defer srv.Close()
	c := srv.Client()
	c.Timeout = time.Second
	defer c.CloseIdleConnections()
	measure("HTTP loopback keepalive", func() error {
		resp, err := c.Get(srv.URL)
		if err != nil {
			return err
		}
		_, err = io.Copy(io.Discard, resp.Body)
		closeErr := resp.Body.Close()
		if err != nil {
			return err
		}
		return closeErr
	})
	f, err := os.CreateTemp("", "design-latency-*")
	if err != nil {
		panic(err)
	}
	defer os.Remove(f.Name())
	defer f.Close()
	data := make([]byte, 4096)
	measure("4KiB WriteAt+Sync", func() error {
		if _, err := f.WriteAt(data, 0); err != nil {
			return err
		}
		return f.Sync()
	})
}
