Documentation
¶
Overview ¶
Package adaptive implements a dual-engine controller that dynamically switches between io_uring and epoll based on runtime telemetry.
The adaptive Engine starts both sub-engines on the same port (via SO_REUSEPORT) and periodically evaluates their performance scores. If the standby engine's historical score exceeds the active engine's score by more than a threshold, the controller triggers a switch. Oscillation detection locks switching for five minutes after three rapid switches.
Users select the adaptive engine via celeris.Config{Engine: celeris.Adaptive}. It is the default engine on Linux.
Index ¶
- type Engine
- func (e *Engine) ActiveEngine() engine.Engine
- func (e *Engine) Addr() net.Addr
- func (e *Engine) ForceSwitch()
- func (e *Engine) FreezeSwitching()
- func (e *Engine) Listen(ctx context.Context) error
- func (e *Engine) Metrics() engine.EngineMetrics
- func (e *Engine) SetFreezeCooldown(d time.Duration)
- func (e *Engine) Shutdown(ctx context.Context) error
- func (e *Engine) Type() engine.EngineType
- func (e *Engine) UnfreezeSwitching()
- type ScoreWeights
- type TelemetrySampler
- type TelemetrySnapshot
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine is an adaptive meta-engine that switches between io_uring and epoll.
func New ¶
New creates a new adaptive engine with epoll as primary and io_uring as secondary. Epoll starts first because it has lower H2 latency on current kernels (single-pass read→process→write vs io_uring's two-iteration CQE model). The controller may switch to io_uring if telemetry indicates it would perform better for the workload. Both sub-engines get the full resource config. This is safe because standby workers are fully suspended (zero CPU, zero connections, listen sockets closed).
func (*Engine) ActiveEngine ¶
ActiveEngine returns the currently active engine.
func (*Engine) ForceSwitch ¶ added in v0.3.5
func (e *Engine) ForceSwitch()
ForceSwitch triggers an immediate engine switch (for testing).
func (*Engine) FreezeSwitching ¶
func (e *Engine) FreezeSwitching()
FreezeSwitching prevents the controller from switching engines.
func (*Engine) Metrics ¶
func (e *Engine) Metrics() engine.EngineMetrics
Metrics aggregates metrics from both sub-engines.
func (*Engine) SetFreezeCooldown ¶ added in v1.1.0
SetFreezeCooldown sets the duration to suppress further switches after a switch. Zero disables the cooldown (default). This prevents oscillation under unstable load.
func (*Engine) UnfreezeSwitching ¶
func (e *Engine) UnfreezeSwitching()
UnfreezeSwitching allows the controller to switch engines again.
type ScoreWeights ¶
type ScoreWeights struct {
// Throughput is the weight applied to requests-per-second in the score.
Throughput float64
// ErrorRate is the penalty weight applied to the error fraction.
ErrorRate float64
}
ScoreWeights defines the weighting for each telemetry signal in score computation. Higher throughput weight favors faster engines; higher error weight penalizes unreliable ones.
func DefaultWeights ¶
func DefaultWeights() ScoreWeights
DefaultWeights returns the default score weights.
type TelemetrySampler ¶
type TelemetrySampler interface {
Sample(e engine.Engine) TelemetrySnapshot
}
TelemetrySampler produces telemetry snapshots from an engine.
type TelemetrySnapshot ¶
type TelemetrySnapshot struct {
// Timestamp is when this snapshot was taken.
Timestamp time.Time
// ThroughputRPS is the recent requests-per-second rate.
ThroughputRPS float64
// ErrorRate is the fraction of requests that resulted in errors (0.0-1.0).
ErrorRate float64
// ActiveConnections is the current number of open connections.
ActiveConnections int64
// CPUUtilization is the estimated CPU usage fraction (0.0-1.0). Currently unused.
CPUUtilization float64
}
TelemetrySnapshot captures a point-in-time view of engine performance, used by the controller to decide whether to switch engines.