mirror of
https://github.com/pomerium/pomerium.git
synced 2025-08-06 10:21:05 +02:00
wip: update request latency test
This commit is contained in:
parent
8049ca54d0
commit
85f06ab36b
2 changed files with 82 additions and 64 deletions
|
@ -1,12 +1,11 @@
|
|||
package benchmarks_test
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand/v2"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pomerium/pomerium/internal/testenv"
|
||||
|
@ -16,12 +15,16 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func BenchmarkRequestLatency(b *testing.B) {
|
||||
for _, n := range []int{1, 10, 100} {
|
||||
b.StopTimer()
|
||||
env := testenv.New(b)
|
||||
var numRoutes int
|
||||
|
||||
func init() {
|
||||
flag.IntVar(&numRoutes, "routes", 100, "number of routes")
|
||||
}
|
||||
|
||||
func TestRequestLatency(t *testing.T) {
|
||||
env := testenv.New(t, testenv.Silent())
|
||||
users := []*scenarios.User{}
|
||||
for i := range n {
|
||||
for i := range numRoutes {
|
||||
users = append(users, &scenarios.User{
|
||||
Email: fmt.Sprintf("user%d@example.com", i),
|
||||
FirstName: fmt.Sprintf("Firstname%d", i),
|
||||
|
@ -34,8 +37,8 @@ func BenchmarkRequestLatency(b *testing.B) {
|
|||
up.Handle("/", func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Write([]byte("OK"))
|
||||
})
|
||||
routes := make([]testenv.Route, n)
|
||||
for i := range n {
|
||||
routes := make([]testenv.Route, numRoutes)
|
||||
for i := range numRoutes {
|
||||
routes[i] = up.Route().
|
||||
From(env.SubdomainURL(fmt.Sprintf("from-%d", i))).
|
||||
PPL(fmt.Sprintf(`{"allow":{"and":["email":{"is":"user%d@example.com"}]}}`, i))
|
||||
|
@ -45,26 +48,27 @@ func BenchmarkRequestLatency(b *testing.B) {
|
|||
env.Start()
|
||||
snippets.WaitStartupComplete(env)
|
||||
|
||||
b.StartTimer()
|
||||
|
||||
b.Run(fmt.Sprintf("routes=%d", n), func(b *testing.B) {
|
||||
indexes := rand.Perm(n)
|
||||
rec := env.NewLogRecorder(testenv.WithSkipCloseDelay())
|
||||
for i := range b.N {
|
||||
idx := indexes[i%n]
|
||||
out := testing.Benchmark(func(b *testing.B) {
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
// rec := env.NewLogRecorder(testenv.WithSkipCloseDelay())
|
||||
for pb.Next() {
|
||||
idx := rand.IntN(numRoutes)
|
||||
resp, err := up.Get(routes[idx], upstreams.AuthenticateAs(fmt.Sprintf("user%d@example.com", idx)))
|
||||
if !assert.NoError(b, err) {
|
||||
rec.DumpToFile(filepath.Join("testdata", strings.ReplaceAll(b.Name(), "/", "_")))
|
||||
// rec.DumpToFile(filepath.Join("testdata", strings.ReplaceAll(b.Name(), "/", "_")))
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(b, resp.StatusCode, 200)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
assert.NoError(b, err)
|
||||
assert.Equal(b, "OK", string(body))
|
||||
}
|
||||
})
|
||||
})
|
||||
t.Log(out)
|
||||
t.Logf("req/s: %f", float64(out.N)/out.T.Seconds())
|
||||
|
||||
env.Stop()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -204,6 +204,7 @@ type environment struct {
|
|||
type EnvironmentOptions struct {
|
||||
debug bool
|
||||
pauseOnFailure bool
|
||||
forceSilent bool
|
||||
}
|
||||
|
||||
type EnvironmentOption func(*EnvironmentOptions)
|
||||
|
@ -232,6 +233,15 @@ func PauseOnFailure(enable ...bool) EnvironmentOption {
|
|||
}
|
||||
}
|
||||
|
||||
func Silent(silent ...bool) EnvironmentOption {
|
||||
if len(silent) == 0 {
|
||||
silent = append(silent, true)
|
||||
}
|
||||
return func(o *EnvironmentOptions) {
|
||||
o.forceSilent = silent[0]
|
||||
}
|
||||
}
|
||||
|
||||
var setGrpcLoggerOnce sync.Once
|
||||
|
||||
func New(t testing.TB, opts ...EnvironmentOption) Environment {
|
||||
|
@ -257,7 +267,7 @@ func New(t testing.TB, opts ...EnvironmentOption) Environment {
|
|||
require.NoError(t, err)
|
||||
|
||||
writer := log.NewMultiWriter()
|
||||
silent := isSilent(t)
|
||||
silent := options.forceSilent || isSilent(t)
|
||||
if silent {
|
||||
log.SetLevel(zerolog.FatalLevel)
|
||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||
|
@ -281,7 +291,8 @@ func New(t testing.TB, opts ...EnvironmentOption) Environment {
|
|||
require: require.New(t),
|
||||
tempDir: t.TempDir(),
|
||||
ports: Ports{
|
||||
Proxy: values.Deferred[int](),
|
||||
ProxyHTTP: values.Deferred[int](),
|
||||
ProxyGRPC: values.Deferred[int](),
|
||||
GRPC: values.Deferred[int](),
|
||||
HTTP: values.Deferred[int](),
|
||||
Outbound: values.Deferred[int](),
|
||||
|
@ -338,7 +349,8 @@ type WithCaller[T any] struct {
|
|||
}
|
||||
|
||||
type Ports struct {
|
||||
Proxy values.MutableValue[int]
|
||||
ProxyHTTP values.MutableValue[int]
|
||||
ProxyGRPC values.MutableValue[int]
|
||||
GRPC values.MutableValue[int]
|
||||
HTTP values.MutableValue[int]
|
||||
Outbound values.MutableValue[int]
|
||||
|
@ -364,7 +376,7 @@ func (e *environment) Require() *require.Assertions {
|
|||
}
|
||||
|
||||
func (e *environment) SubdomainURL(subdomain string) values.Value[string] {
|
||||
return values.Bind(e.ports.Proxy, func(port int) string {
|
||||
return values.Bind(e.ports.ProxyHTTP, func(port int) string {
|
||||
return fmt.Sprintf("https://%s.%s:%d", subdomain, e.domain, port)
|
||||
})
|
||||
}
|
||||
|
@ -425,7 +437,7 @@ func (e *environment) Start() {
|
|||
cfg := &config.Config{
|
||||
Options: config.NewDefaultOptions(),
|
||||
}
|
||||
ports, err := netutil.AllocatePorts(7)
|
||||
ports, err := netutil.AllocatePorts(8)
|
||||
require.NoError(e.t, err)
|
||||
atoi := func(str string) int {
|
||||
p, err := strconv.Atoi(str)
|
||||
|
@ -434,20 +446,22 @@ func (e *environment) Start() {
|
|||
}
|
||||
return p
|
||||
}
|
||||
e.ports.Proxy.Resolve(atoi(ports[0]))
|
||||
e.ports.GRPC.Resolve(atoi(ports[1]))
|
||||
e.ports.HTTP.Resolve(atoi(ports[2]))
|
||||
e.ports.Outbound.Resolve(atoi(ports[3]))
|
||||
e.ports.Metrics.Resolve(atoi(ports[4]))
|
||||
e.ports.Debug.Resolve(atoi(ports[5]))
|
||||
e.ports.ALPN.Resolve(atoi(ports[6]))
|
||||
cfg.AllocatePorts(*(*[6]string)(ports[1:]))
|
||||
e.ports.ProxyHTTP.Resolve(atoi(ports[0]))
|
||||
e.ports.ProxyGRPC.Resolve(atoi(ports[1]))
|
||||
e.ports.GRPC.Resolve(atoi(ports[2]))
|
||||
e.ports.HTTP.Resolve(atoi(ports[3]))
|
||||
e.ports.Outbound.Resolve(atoi(ports[4]))
|
||||
e.ports.Metrics.Resolve(atoi(ports[5]))
|
||||
e.ports.Debug.Resolve(atoi(ports[6]))
|
||||
e.ports.ALPN.Resolve(atoi(ports[7]))
|
||||
cfg.AllocatePorts(*(*[6]string)(ports[2:]))
|
||||
|
||||
cfg.Options.AutocertOptions = config.AutocertOptions{Enable: false}
|
||||
cfg.Options.Services = "all"
|
||||
cfg.Options.LogLevel = config.LogLevelDebug
|
||||
cfg.Options.ProxyLogLevel = config.LogLevelInfo
|
||||
cfg.Options.Addr = fmt.Sprintf("127.0.0.1:%d", e.ports.Proxy.Value())
|
||||
cfg.Options.Addr = fmt.Sprintf("127.0.0.1:%d", e.ports.ProxyHTTP.Value())
|
||||
cfg.Options.GRPCAddr = fmt.Sprintf("127.0.0.1:%d", e.ports.ProxyGRPC.Value())
|
||||
cfg.Options.CAFile = filepath.Join(e.tempDir, "certs", "ca.pem")
|
||||
cfg.Options.CertFile = filepath.Join(e.tempDir, "certs", "trusted.pem")
|
||||
cfg.Options.KeyFile = filepath.Join(e.tempDir, "certs", "trusted-key.pem")
|
||||
|
@ -707,8 +721,8 @@ func (e *environment) ReportOK(_ health.Check, _ ...health.Attr) {}
|
|||
func (e *environment) advanceState(newState EnvironmentState) {
|
||||
e.stateMu.Lock()
|
||||
defer e.stateMu.Unlock()
|
||||
if e.state != newState>>1 {
|
||||
panic(fmt.Sprintf("internal test environment bug: invalid state: expected=%s, actual=%s", newState>>1, e.state))
|
||||
if newState <= e.state {
|
||||
panic(fmt.Sprintf("internal test environment bug: changed state to <= current: newState=%s, current=%s", newState, e.state))
|
||||
}
|
||||
e.debugf("state %s -> %s", e.state.String(), newState.String())
|
||||
e.state = newState
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue