mirror of
https://github.com/jetkvm/kvm.git
synced 2025-09-16 08:38:14 +00:00
Update config field names to better reflect their specific usage contexts in adaptive buffer and optimizer components. This improves code maintainability by making the purpose of each latency target more explicit.
199 lines
6.4 KiB
Go
199 lines
6.4 KiB
Go
package audio
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
// AdaptiveOptimizer automatically adjusts audio parameters based on latency metrics
|
|
type AdaptiveOptimizer struct {
|
|
// Atomic fields MUST be first for ARM32 alignment (int64 fields need 8-byte alignment)
|
|
optimizationCount int64 // Number of optimizations performed (atomic)
|
|
lastOptimization int64 // Timestamp of last optimization (atomic)
|
|
optimizationLevel int64 // Current optimization level (0-10) (atomic)
|
|
|
|
latencyMonitor *LatencyMonitor
|
|
bufferManager *AdaptiveBufferManager
|
|
logger zerolog.Logger
|
|
|
|
// Control channels
|
|
ctx context.Context
|
|
cancel context.CancelFunc
|
|
wg sync.WaitGroup
|
|
|
|
// Configuration
|
|
config OptimizerConfig
|
|
}
|
|
|
|
// OptimizerConfig holds configuration for the adaptive optimizer
|
|
type OptimizerConfig struct {
|
|
MaxOptimizationLevel int // Maximum optimization level (0-10)
|
|
CooldownPeriod time.Duration // Minimum time between optimizations
|
|
Aggressiveness float64 // How aggressively to optimize (0.0-1.0)
|
|
RollbackThreshold time.Duration // Latency threshold to rollback optimizations
|
|
StabilityPeriod time.Duration // Time to wait for stability after optimization
|
|
}
|
|
|
|
// DefaultOptimizerConfig returns a sensible default configuration
|
|
func DefaultOptimizerConfig() OptimizerConfig {
|
|
return OptimizerConfig{
|
|
MaxOptimizationLevel: 8,
|
|
CooldownPeriod: GetConfig().CooldownPeriod,
|
|
Aggressiveness: GetConfig().OptimizerAggressiveness,
|
|
RollbackThreshold: GetConfig().RollbackThreshold,
|
|
StabilityPeriod: GetConfig().AdaptiveOptimizerStability,
|
|
}
|
|
}
|
|
|
|
// NewAdaptiveOptimizer creates a new adaptive optimizer
|
|
func NewAdaptiveOptimizer(latencyMonitor *LatencyMonitor, bufferManager *AdaptiveBufferManager, config OptimizerConfig, logger zerolog.Logger) *AdaptiveOptimizer {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
optimizer := &AdaptiveOptimizer{
|
|
latencyMonitor: latencyMonitor,
|
|
bufferManager: bufferManager,
|
|
config: config,
|
|
logger: logger.With().Str("component", "adaptive-optimizer").Logger(),
|
|
ctx: ctx,
|
|
cancel: cancel,
|
|
}
|
|
|
|
// Register as latency monitor callback
|
|
latencyMonitor.AddOptimizationCallback(optimizer.handleLatencyOptimization)
|
|
|
|
return optimizer
|
|
}
|
|
|
|
// Start begins the adaptive optimization process
|
|
func (ao *AdaptiveOptimizer) Start() {
|
|
ao.wg.Add(1)
|
|
go ao.optimizationLoop()
|
|
ao.logger.Debug().Msg("adaptive optimizer started")
|
|
}
|
|
|
|
// Stop stops the adaptive optimizer
|
|
func (ao *AdaptiveOptimizer) Stop() {
|
|
ao.cancel()
|
|
ao.wg.Wait()
|
|
ao.logger.Debug().Msg("adaptive optimizer stopped")
|
|
}
|
|
|
|
// initializeStrategies sets up the available optimization strategies
|
|
|
|
// handleLatencyOptimization is called when latency optimization is needed
|
|
func (ao *AdaptiveOptimizer) handleLatencyOptimization(metrics LatencyMetrics) error {
|
|
currentLevel := atomic.LoadInt64(&ao.optimizationLevel)
|
|
lastOpt := atomic.LoadInt64(&ao.lastOptimization)
|
|
|
|
// Check cooldown period
|
|
if time.Since(time.Unix(0, lastOpt)) < ao.config.CooldownPeriod {
|
|
return nil
|
|
}
|
|
|
|
// Determine if we need to increase or decrease optimization level
|
|
targetLevel := ao.calculateTargetOptimizationLevel(metrics)
|
|
|
|
if targetLevel > currentLevel {
|
|
return ao.increaseOptimization(int(targetLevel))
|
|
} else if targetLevel < currentLevel {
|
|
return ao.decreaseOptimization(int(targetLevel))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// calculateTargetOptimizationLevel determines the appropriate optimization level
|
|
func (ao *AdaptiveOptimizer) calculateTargetOptimizationLevel(metrics LatencyMetrics) int64 {
|
|
// Base calculation on current latency vs target
|
|
latencyRatio := float64(metrics.Current) / float64(GetConfig().AdaptiveOptimizerLatencyTarget) // 50ms target
|
|
|
|
// Adjust based on trend
|
|
switch metrics.Trend {
|
|
case LatencyTrendIncreasing:
|
|
latencyRatio *= 1.2 // Be more aggressive
|
|
case LatencyTrendDecreasing:
|
|
latencyRatio *= 0.8 // Be less aggressive
|
|
case LatencyTrendVolatile:
|
|
latencyRatio *= 1.1 // Slightly more aggressive
|
|
}
|
|
|
|
// Apply aggressiveness factor
|
|
latencyRatio *= ao.config.Aggressiveness
|
|
|
|
// Convert to optimization level
|
|
targetLevel := int64(latencyRatio * GetConfig().LatencyScalingFactor) // Scale to 0-10 range
|
|
if targetLevel > int64(ao.config.MaxOptimizationLevel) {
|
|
targetLevel = int64(ao.config.MaxOptimizationLevel)
|
|
}
|
|
if targetLevel < 0 {
|
|
targetLevel = 0
|
|
}
|
|
|
|
return targetLevel
|
|
}
|
|
|
|
// increaseOptimization applies optimization strategies up to the target level
|
|
func (ao *AdaptiveOptimizer) increaseOptimization(targetLevel int) error {
|
|
atomic.StoreInt64(&ao.optimizationLevel, int64(targetLevel))
|
|
atomic.StoreInt64(&ao.lastOptimization, time.Now().UnixNano())
|
|
atomic.AddInt64(&ao.optimizationCount, 1)
|
|
|
|
return nil
|
|
}
|
|
|
|
// decreaseOptimization rolls back optimization strategies to the target level
|
|
func (ao *AdaptiveOptimizer) decreaseOptimization(targetLevel int) error {
|
|
atomic.StoreInt64(&ao.optimizationLevel, int64(targetLevel))
|
|
atomic.StoreInt64(&ao.lastOptimization, time.Now().UnixNano())
|
|
|
|
return nil
|
|
}
|
|
|
|
// optimizationLoop runs the main optimization monitoring loop
|
|
func (ao *AdaptiveOptimizer) optimizationLoop() {
|
|
defer ao.wg.Done()
|
|
|
|
ticker := time.NewTicker(ao.config.StabilityPeriod)
|
|
defer ticker.Stop()
|
|
|
|
for {
|
|
select {
|
|
case <-ao.ctx.Done():
|
|
return
|
|
case <-ticker.C:
|
|
ao.checkStability()
|
|
}
|
|
}
|
|
}
|
|
|
|
// checkStability monitors system stability and rolls back if needed
|
|
func (ao *AdaptiveOptimizer) checkStability() {
|
|
metrics := ao.latencyMonitor.GetMetrics()
|
|
|
|
// Check if we need to rollback due to excessive latency
|
|
if metrics.Current > ao.config.RollbackThreshold {
|
|
currentLevel := int(atomic.LoadInt64(&ao.optimizationLevel))
|
|
if currentLevel > 0 {
|
|
ao.logger.Warn().Dur("current_latency", metrics.Current).Dur("threshold", ao.config.RollbackThreshold).Msg("rolling back optimizations due to excessive latency")
|
|
if err := ao.decreaseOptimization(currentLevel - 1); err != nil {
|
|
ao.logger.Error().Err(err).Msg("failed to decrease optimization level")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// GetOptimizationStats returns current optimization statistics
|
|
func (ao *AdaptiveOptimizer) GetOptimizationStats() map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"optimization_level": atomic.LoadInt64(&ao.optimizationLevel),
|
|
"optimization_count": atomic.LoadInt64(&ao.optimizationCount),
|
|
"last_optimization": time.Unix(0, atomic.LoadInt64(&ao.lastOptimization)),
|
|
}
|
|
}
|
|
|
|
// Strategy implementation methods (stubs for now)
|