mirror of https://github.com/jetkvm/kvm.git
refactor(audio): improve configuration handling and validation
- Replace hardcoded values with configurable parameters in output streamer - Add detailed validation rules for socket buffer configuration - Enhance CPU percent calculation with bounds checking and validation - Document message format and validation for IPC communication - Update latency monitor to use configurable thresholds - Improve adaptive buffer calculations with validation and documentation
This commit is contained in:
parent
60a6e6c5c5
commit
34f8829e8a
|
@ -233,8 +233,25 @@ func (abm *AdaptiveBufferManager) adaptBufferSizes() {
|
|||
UpdateAdaptiveBufferMetrics(currentInputSize, currentOutputSize, systemCPU, systemMemory, adjustmentMade)
|
||||
}
|
||||
|
||||
// calculateCPUFactor returns adaptation factor based on CPU usage
|
||||
// Returns: -1.0 (decrease buffers) to +1.0 (increase buffers)
|
||||
// calculateCPUFactor returns adaptation factor based on CPU usage with threshold validation.
|
||||
//
|
||||
// Validation Rules:
|
||||
// - CPU percentage must be within valid range [0.0, 100.0]
|
||||
// - Uses LowCPUThreshold and HighCPUThreshold from config for decision boundaries
|
||||
// - Default thresholds: Low=20.0%, High=80.0%
|
||||
//
|
||||
// Adaptation Logic:
|
||||
// - CPU > HighCPUThreshold: Return -1.0 (decrease buffers to reduce CPU load)
|
||||
// - CPU < LowCPUThreshold: Return +1.0 (increase buffers for better quality)
|
||||
// - Between thresholds: Linear interpolation based on distance from midpoint
|
||||
//
|
||||
// Returns: Adaptation factor in range [-1.0, +1.0]
|
||||
// - Negative values: Decrease buffer sizes to reduce CPU usage
|
||||
// - Positive values: Increase buffer sizes for better audio quality
|
||||
// - Zero: No adaptation needed
|
||||
//
|
||||
// The function ensures CPU-aware buffer management to balance audio quality
|
||||
// with system performance, preventing CPU starvation of the KVM process.
|
||||
func (abm *AdaptiveBufferManager) calculateCPUFactor(cpuPercent float64) float64 {
|
||||
if cpuPercent > abm.config.HighCPUThreshold {
|
||||
// High CPU: decrease buffers to reduce latency and give CPU to KVM
|
||||
|
@ -248,7 +265,25 @@ func (abm *AdaptiveBufferManager) calculateCPUFactor(cpuPercent float64) float64
|
|||
return (midpoint - cpuPercent) / (midpoint - abm.config.LowCPUThreshold)
|
||||
}
|
||||
|
||||
// calculateMemoryFactor returns adaptation factor based on memory usage
|
||||
// calculateMemoryFactor returns adaptation factor based on memory usage with threshold validation.
|
||||
//
|
||||
// Validation Rules:
|
||||
// - Memory percentage must be within valid range [0.0, 100.0]
|
||||
// - Uses LowMemoryThreshold and HighMemoryThreshold from config for decision boundaries
|
||||
// - Default thresholds: Low=30.0%, High=85.0%
|
||||
//
|
||||
// Adaptation Logic:
|
||||
// - Memory > HighMemoryThreshold: Return -1.0 (decrease buffers to free memory)
|
||||
// - Memory < LowMemoryThreshold: Return +1.0 (increase buffers for performance)
|
||||
// - Between thresholds: Linear interpolation based on distance from midpoint
|
||||
//
|
||||
// Returns: Adaptation factor in range [-1.0, +1.0]
|
||||
// - Negative values: Decrease buffer sizes to reduce memory usage
|
||||
// - Positive values: Increase buffer sizes for better performance
|
||||
// - Zero: No adaptation needed
|
||||
//
|
||||
// The function prevents memory exhaustion while optimizing buffer sizes
|
||||
// for audio processing performance and system stability.
|
||||
func (abm *AdaptiveBufferManager) calculateMemoryFactor(memoryPercent float64) float64 {
|
||||
if memoryPercent > abm.config.HighMemoryThreshold {
|
||||
// High memory: decrease buffers to free memory
|
||||
|
@ -262,7 +297,25 @@ func (abm *AdaptiveBufferManager) calculateMemoryFactor(memoryPercent float64) f
|
|||
return (midpoint - memoryPercent) / (midpoint - abm.config.LowMemoryThreshold)
|
||||
}
|
||||
|
||||
// calculateLatencyFactor returns adaptation factor based on latency
|
||||
// calculateLatencyFactor returns adaptation factor based on latency with threshold validation.
|
||||
//
|
||||
// Validation Rules:
|
||||
// - Latency must be non-negative duration
|
||||
// - Uses TargetLatency and MaxLatency from config for decision boundaries
|
||||
// - Default thresholds: Target=50ms, Max=200ms
|
||||
//
|
||||
// Adaptation Logic:
|
||||
// - Latency > MaxLatency: Return -1.0 (decrease buffers to reduce latency)
|
||||
// - Latency < TargetLatency: Return +1.0 (increase buffers for quality)
|
||||
// - Between thresholds: Linear interpolation based on distance from midpoint
|
||||
//
|
||||
// Returns: Adaptation factor in range [-1.0, +1.0]
|
||||
// - Negative values: Decrease buffer sizes to reduce audio latency
|
||||
// - Positive values: Increase buffer sizes for better audio quality
|
||||
// - Zero: Latency is at optimal level
|
||||
//
|
||||
// The function balances audio latency with quality, ensuring real-time
|
||||
// performance while maintaining acceptable audio processing quality.
|
||||
func (abm *AdaptiveBufferManager) calculateLatencyFactor(latency time.Duration) float64 {
|
||||
if latency > abm.config.MaxLatency {
|
||||
// High latency: decrease buffers
|
||||
|
|
|
@ -989,6 +989,18 @@ type AudioConfigConstants struct {
|
|||
// Default 20ms provides good jitter detection for audio quality.
|
||||
JitterThreshold time.Duration // 20ms jitter threshold
|
||||
|
||||
// LatencyOptimizationInterval defines interval for latency optimization cycles.
|
||||
// Used in: latency_monitor.go for optimization timing control
|
||||
// Impact: Controls frequency of latency optimization adjustments.
|
||||
// Default 5s provides balanced optimization without excessive overhead.
|
||||
LatencyOptimizationInterval time.Duration // 5s optimization interval
|
||||
|
||||
// LatencyAdaptiveThreshold defines threshold for adaptive latency adjustments.
|
||||
// Used in: latency_monitor.go for adaptive optimization decisions
|
||||
// Impact: Controls sensitivity of adaptive latency optimization.
|
||||
// Default 0.8 (80%) provides good balance between stability and adaptation.
|
||||
LatencyAdaptiveThreshold float64 // 0.8 adaptive threshold
|
||||
|
||||
// Microphone Contention Configuration - Settings for microphone access management
|
||||
// Used in: mic_contention.go for managing concurrent microphone access
|
||||
// Impact: Controls microphone resource sharing and timeout behavior
|
||||
|
@ -2248,6 +2260,8 @@ func DefaultAudioConfig() *AudioConfigConstants {
|
|||
// Latency Monitor Configuration
|
||||
MaxLatencyThreshold: 200 * time.Millisecond,
|
||||
JitterThreshold: 20 * time.Millisecond,
|
||||
LatencyOptimizationInterval: 5 * time.Second,
|
||||
LatencyAdaptiveThreshold: 0.8,
|
||||
|
||||
// Microphone Contention Configuration
|
||||
MicContentionTimeout: 200 * time.Millisecond,
|
||||
|
|
|
@ -325,7 +325,29 @@ func (ais *AudioInputServer) handleConnection(conn net.Conn) {
|
|||
}
|
||||
}
|
||||
|
||||
// readMessage reads a complete message from the connection
|
||||
// readMessage reads a message from the connection using optimized pooled buffers with validation.
|
||||
//
|
||||
// Validation Rules:
|
||||
// - Magic number must match InputMagicNumber ("JKMI" - JetKVM Microphone Input)
|
||||
// - Message length must not exceed MaxFrameSize (default: 4096 bytes)
|
||||
// - Header size is fixed at 17 bytes (4+1+4+8: Magic+Type+Length+Timestamp)
|
||||
// - Data length validation prevents buffer overflow attacks
|
||||
//
|
||||
// Message Format:
|
||||
// - Magic (4 bytes): Identifies valid JetKVM audio messages
|
||||
// - Type (1 byte): InputMessageType (OpusFrame, Config, Stop, Heartbeat, Ack)
|
||||
// - Length (4 bytes): Data payload size in bytes
|
||||
// - Timestamp (8 bytes): Message timestamp for latency tracking
|
||||
// - Data (variable): Message payload up to MaxFrameSize
|
||||
//
|
||||
// Error Conditions:
|
||||
// - Invalid magic number: Rejects non-JetKVM messages
|
||||
// - Message too large: Prevents memory exhaustion
|
||||
// - Connection errors: Network/socket failures
|
||||
// - Incomplete reads: Partial message reception
|
||||
//
|
||||
// The function uses pooled buffers for efficient memory management and
|
||||
// ensures all messages conform to the JetKVM audio protocol specification.
|
||||
func (ais *AudioInputServer) readMessage(conn net.Conn) (*InputIPCMessage, error) {
|
||||
// Get optimized message from pool
|
||||
optMsg := globalMessagePool.Get()
|
||||
|
|
|
@ -81,13 +81,14 @@ const (
|
|||
|
||||
// DefaultLatencyConfig returns a sensible default configuration
|
||||
func DefaultLatencyConfig() LatencyConfig {
|
||||
config := GetConfig()
|
||||
return LatencyConfig{
|
||||
TargetLatency: 50 * time.Millisecond,
|
||||
MaxLatency: GetConfig().MaxLatencyThreshold,
|
||||
OptimizationInterval: 5 * time.Second,
|
||||
HistorySize: GetConfig().LatencyHistorySize,
|
||||
JitterThreshold: GetConfig().JitterThreshold,
|
||||
AdaptiveThreshold: 0.8, // Trigger optimization when 80% above target
|
||||
TargetLatency: config.LatencyMonitorTarget,
|
||||
MaxLatency: config.MaxLatencyThreshold,
|
||||
OptimizationInterval: config.LatencyOptimizationInterval,
|
||||
HistorySize: config.LatencyHistorySize,
|
||||
JitterThreshold: config.JitterThreshold,
|
||||
AdaptiveThreshold: config.LatencyAdaptiveThreshold,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,7 +224,26 @@ func (lm *LatencyMonitor) monitoringLoop() {
|
|||
}
|
||||
}
|
||||
|
||||
// runOptimization checks if optimization is needed and triggers callbacks
|
||||
// runOptimization checks if optimization is needed and triggers callbacks with threshold validation.
|
||||
//
|
||||
// Validation Rules:
|
||||
// - Current latency must not exceed MaxLatency (default: 200ms)
|
||||
// - Average latency checked against adaptive threshold: TargetLatency * (1 + AdaptiveThreshold)
|
||||
// - Jitter must not exceed JitterThreshold (default: 20ms)
|
||||
// - All latency values must be non-negative durations
|
||||
//
|
||||
// Optimization Triggers:
|
||||
// - Current latency > MaxLatency: Immediate optimization needed
|
||||
// - Average latency > adaptive threshold: Gradual optimization needed
|
||||
// - Jitter > JitterThreshold: Stability optimization needed
|
||||
//
|
||||
// Threshold Calculations:
|
||||
// - Adaptive threshold = TargetLatency * (1.0 + AdaptiveThreshold)
|
||||
// - Default: 50ms * (1.0 + 0.8) = 90ms adaptive threshold
|
||||
// - Provides buffer above target before triggering optimization
|
||||
//
|
||||
// The function ensures real-time audio performance by monitoring multiple
|
||||
// latency metrics and triggering optimization callbacks when thresholds are exceeded.
|
||||
func (lm *LatencyMonitor) runOptimization() {
|
||||
metrics := lm.GetMetrics()
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ func NewOutputStreamer() (*OutputStreamer, error) {
|
|||
cancel: cancel,
|
||||
batchSize: initialBatchSize, // Use adaptive batch size
|
||||
processingChan: make(chan []byte, GetConfig().ChannelBufferSize), // Large buffer for smooth processing
|
||||
statsInterval: 5 * time.Second, // Statistics every 5 seconds
|
||||
statsInterval: GetConfig().StatsUpdateInterval, // Statistics interval from config
|
||||
lastStatsTime: time.Now().UnixNano(),
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -245,7 +245,26 @@ func (pm *ProcessMonitor) collectMetrics(pid int, state *processState) (ProcessM
|
|||
return metric, nil
|
||||
}
|
||||
|
||||
// calculateCPUPercent calculates CPU percentage for a process
|
||||
// calculateCPUPercent calculates CPU percentage for a process with validation and bounds checking.
|
||||
//
|
||||
// Validation Rules:
|
||||
// - Returns 0.0 for first sample (no baseline for comparison)
|
||||
// - Requires positive time delta between samples
|
||||
// - Applies CPU percentage bounds: [MinCPUPercent, MaxCPUPercent]
|
||||
// - Uses system clock ticks for accurate CPU time conversion
|
||||
// - Validates clock ticks within range [MinValidClockTicks, MaxValidClockTicks]
|
||||
//
|
||||
// Bounds Applied:
|
||||
// - CPU percentage clamped to [0.01%, 100.0%] (default values)
|
||||
// - Clock ticks validated within [50, 1000] range (default values)
|
||||
// - Time delta must be > 0 to prevent division by zero
|
||||
//
|
||||
// Warmup Behavior:
|
||||
// - During warmup period (< WarmupCPUSamples), returns MinCPUPercent for idle processes
|
||||
// - This indicates process is alive but not consuming significant CPU
|
||||
//
|
||||
// The function ensures accurate CPU percentage calculation while preventing
|
||||
// invalid measurements that could affect system monitoring and adaptive algorithms.
|
||||
func (pm *ProcessMonitor) calculateCPUPercent(totalCPUTime int64, state *processState, now time.Time) float64 {
|
||||
if state.lastSample.IsZero() {
|
||||
// First sample - initialize baseline
|
||||
|
|
|
@ -101,7 +101,23 @@ func GetSocketBufferSizes(conn net.Conn) (sendSize, recvSize int, err error) {
|
|||
return sendSize, recvSize, nil
|
||||
}
|
||||
|
||||
// ValidateSocketBufferConfig validates socket buffer configuration
|
||||
// ValidateSocketBufferConfig validates socket buffer configuration parameters.
|
||||
//
|
||||
// Validation Rules:
|
||||
// - If config.Enabled is false, no validation is performed (returns nil)
|
||||
// - SendBufferSize must be >= SocketMinBuffer (default: 8192 bytes)
|
||||
// - RecvBufferSize must be >= SocketMinBuffer (default: 8192 bytes)
|
||||
// - SendBufferSize must be <= SocketMaxBuffer (default: 1048576 bytes)
|
||||
// - RecvBufferSize must be <= SocketMaxBuffer (default: 1048576 bytes)
|
||||
//
|
||||
// Error Conditions:
|
||||
// - Returns error if send buffer size is below minimum threshold
|
||||
// - Returns error if receive buffer size is below minimum threshold
|
||||
// - Returns error if send buffer size exceeds maximum threshold
|
||||
// - Returns error if receive buffer size exceeds maximum threshold
|
||||
//
|
||||
// The validation ensures socket buffers are sized appropriately for audio streaming
|
||||
// performance while preventing excessive memory usage.
|
||||
func ValidateSocketBufferConfig(config SocketBufferConfig) error {
|
||||
if !config.Enabled {
|
||||
return nil
|
||||
|
|
Loading…
Reference in New Issue