Skip to main content

vtcode_config/
optimization.rs

1//! Configuration for performance optimization features
2
3use serde::{Deserialize, Serialize};
4
5/// Configuration for all optimization features
6#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
7#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8pub struct OptimizationConfig {
9    /// Memory pool configuration
10    #[serde(default)]
11    pub memory_pool: MemoryPoolConfig,
12
13    /// Tool registry optimization settings
14    #[serde(default)]
15    pub tool_registry: ToolRegistryConfig,
16
17    /// Async pipeline configuration
18    #[serde(default)]
19    async_pipeline: AsyncPipelineConfig,
20
21    /// LLM client optimization settings
22    #[serde(default)]
23    llm_client: LLMClientConfig,
24
25    /// Agent execution optimization
26    #[serde(default)]
27    pub agent_execution: AgentExecutionConfig,
28
29    /// Performance profiling settings
30    #[serde(default)]
31    profiling: ProfilingConfig,
32
33    /// File read cache configuration
34    #[serde(default)]
35    pub file_read_cache: FileReadCacheConfig,
36
37    /// Read-only command result cache
38    #[serde(default)]
39    pub command_cache: CommandCacheConfig,
40}
41
42/// File read cache configuration
43#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
44#[derive(Debug, Clone, Serialize, Deserialize)]
45#[serde(default)]
46pub struct FileReadCacheConfig {
47    /// Enable file read caching
48    pub enabled: bool,
49
50    /// Minimum file size (bytes) before caching
51    pub min_size_bytes: usize,
52
53    /// Maximum cached file size (bytes)
54    pub max_size_bytes: usize,
55
56    /// Cache TTL in seconds
57    pub ttl_secs: u64,
58
59    /// Maximum number of cached entries
60    max_entries: usize,
61
62    /// Absolute ceiling (in lines) for a single line-based `read_file` call.
63    /// Any read requesting more lines is clamped to this value and the response
64    /// exposes a `next_read_args` continuation to read the remainder.
65    #[serde(default = "default_max_read_lines")]
66    pub max_read_lines: usize,
67}
68
69/// Serde default for [`FileReadCacheConfig::max_read_lines`].
70fn default_max_read_lines() -> usize {
71    crate::constants::optimization::DEFAULT_MAX_READ_LINES
72}
73
74/// Read-only command cache configuration
75#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
76#[derive(Debug, Clone, Serialize, Deserialize)]
77#[serde(default)]
78pub struct CommandCacheConfig {
79    /// Enable command caching
80    pub enabled: bool,
81
82    /// Cache TTL in milliseconds
83    pub ttl_ms: u64,
84
85    /// Maximum number of cached entries
86    pub max_entries: usize,
87
88    /// Allowlist of command prefixes eligible for caching
89    pub allowlist: Vec<String>,
90}
91
92/// Memory pool configuration
93#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
94#[derive(Debug, Clone, Serialize, Deserialize)]
95#[serde(default)]
96pub struct MemoryPoolConfig {
97    /// Enable memory pool (can be disabled for debugging)
98    pub enabled: bool,
99
100    /// Maximum number of strings to pool
101    pub max_string_pool_size: usize,
102
103    /// Maximum number of Values to pool
104    pub max_value_pool_size: usize,
105
106    /// Maximum number of `Vec<String>` to pool
107    pub max_vec_pool_size: usize,
108}
109
110/// Tool registry optimization configuration
111#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
112#[derive(Debug, Clone, Serialize, Deserialize)]
113#[serde(default)]
114pub struct ToolRegistryConfig {
115    /// Enable optimized registry
116    pub use_optimized_registry: bool,
117
118    /// Maximum concurrent tool executions
119    max_concurrent_tools: usize,
120
121    /// Hot cache size for frequently used tools
122    pub hot_cache_size: usize,
123
124    /// Tool execution timeout in seconds
125    default_timeout_secs: u64,
126
127    /// When `true`, middleware `before_execute` failures are logged but do
128    /// not block the tool call (fail-open). When `false` (the default),
129    /// middleware errors deny execution (fail-closed).
130    pub middleware_fail_open: bool,
131}
132
133/// Async pipeline configuration
134#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
135#[derive(Debug, Clone, Serialize, Deserialize)]
136#[serde(default)]
137pub struct AsyncPipelineConfig {
138    /// Enable request batching
139    enable_batching: bool,
140
141    /// Enable result caching
142    enable_caching: bool,
143
144    /// Maximum batch size for tool requests
145    max_batch_size: usize,
146
147    /// Batch timeout in milliseconds
148    batch_timeout_ms: u64,
149
150    /// Result cache size
151    cache_size: usize,
152}
153
154/// LLM client optimization configuration
155#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
156#[derive(Debug, Clone, Serialize, Deserialize)]
157#[serde(default)]
158pub struct LLMClientConfig {
159    /// Enable connection pooling
160    enable_connection_pooling: bool,
161
162    /// Enable response caching
163    enable_response_caching: bool,
164
165    /// Enable request batching
166    enable_request_batching: bool,
167
168    /// Connection pool size
169    connection_pool_size: usize,
170
171    /// Response cache size
172    response_cache_size: usize,
173
174    /// Response cache TTL in seconds
175    cache_ttl_secs: u64,
176
177    /// Rate limit: requests per second
178    rate_limit_rps: f64,
179
180    /// Rate limit burst capacity
181    rate_limit_burst: usize,
182}
183
184/// Agent execution optimization configuration
185#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
186#[derive(Debug, Clone, Serialize, Deserialize)]
187#[serde(default)]
188pub struct AgentExecutionConfig {
189    /// Enable optimized agent execution loop
190    use_optimized_loop: bool,
191
192    /// Enable performance prediction
193    enable_performance_prediction: bool,
194
195    /// State transition history size
196    state_history_size: usize,
197
198    /// Resource monitoring interval in milliseconds
199    resource_monitor_interval_ms: u64,
200
201    /// Maximum memory usage in MB
202    max_memory_mb: u64,
203
204    /// Maximum execution time in seconds
205    pub max_execution_time_secs: u64,
206
207    /// Idle detection timeout in milliseconds (0 to disable)
208    /// When the agent is idle for this duration, it will enter a low-power state
209    pub idle_timeout_ms: u64,
210
211    /// Back-off duration in milliseconds when no work is pending
212    /// This reduces CPU usage during idle periods
213    pub idle_backoff_ms: u64,
214
215    /// Maximum consecutive idle cycles before entering deep sleep
216    pub max_idle_cycles: usize,
217}
218
219/// Performance profiling configuration
220#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
221#[derive(Debug, Clone, Serialize, Deserialize)]
222#[serde(default)]
223pub struct ProfilingConfig {
224    /// Enable performance profiling
225    enabled: bool,
226
227    /// Resource monitoring interval in milliseconds
228    monitor_interval_ms: u64,
229
230    /// Maximum benchmark history size
231    max_history_size: usize,
232
233    /// Auto-export results to file
234    auto_export_results: bool,
235
236    /// Export file path
237    export_file_path: String,
238
239    /// Enable regression testing
240    enable_regression_testing: bool,
241
242    /// Maximum allowed performance regression percentage
243    max_regression_percent: f64,
244}
245
246impl Default for MemoryPoolConfig {
247    fn default() -> Self {
248        Self {
249            enabled: true,
250            max_string_pool_size: 64,
251            max_value_pool_size: 32,
252            max_vec_pool_size: 16,
253        }
254    }
255}
256
257impl Default for FileReadCacheConfig {
258    fn default() -> Self {
259        Self {
260            enabled: true,
261            min_size_bytes: crate::constants::optimization::FILE_READ_CACHE_MIN_SIZE_BYTES,
262            max_size_bytes: crate::constants::optimization::FILE_READ_CACHE_MAX_SIZE_BYTES,
263            ttl_secs: crate::constants::optimization::FILE_READ_CACHE_TTL_SECS,
264            max_entries: crate::constants::optimization::FILE_READ_CACHE_MAX_ENTRIES,
265            max_read_lines: crate::constants::optimization::DEFAULT_MAX_READ_LINES,
266        }
267    }
268}
269
270impl Default for CommandCacheConfig {
271    fn default() -> Self {
272        Self {
273            enabled: true,
274            ttl_ms: crate::constants::optimization::COMMAND_CACHE_TTL_MS,
275            max_entries: crate::constants::optimization::COMMAND_CACHE_MAX_ENTRIES,
276            allowlist: crate::constants::optimization::COMMAND_CACHE_ALLOWLIST
277                .iter()
278                .map(|s| s.to_string())
279                .collect(),
280        }
281    }
282}
283
284impl Default for ToolRegistryConfig {
285    fn default() -> Self {
286        Self {
287            use_optimized_registry: true, // Enable by default for better performance
288            max_concurrent_tools: 4,
289            hot_cache_size: 16,
290            default_timeout_secs: 180,
291            middleware_fail_open: false, // Fail-closed by default; opt-in to fail-open
292        }
293    }
294}
295
296impl Default for AsyncPipelineConfig {
297    fn default() -> Self {
298        Self {
299            enable_batching: false, // Conservative default
300            enable_caching: true,
301            max_batch_size: 5,
302            batch_timeout_ms: 100,
303            cache_size: 100,
304        }
305    }
306}
307
308impl Default for LLMClientConfig {
309    fn default() -> Self {
310        Self {
311            enable_connection_pooling: false, // Conservative default
312            enable_response_caching: true,
313            enable_request_batching: false, // Conservative default
314            connection_pool_size: 4,
315            response_cache_size: 50,
316            cache_ttl_secs: 300,
317            rate_limit_rps: 10.0,
318            rate_limit_burst: 20,
319        }
320    }
321}
322
323impl Default for AgentExecutionConfig {
324    fn default() -> Self {
325        Self {
326            use_optimized_loop: true,             // Enable by default for better performance
327            enable_performance_prediction: false, // Conservative default
328            state_history_size: 1000,
329            resource_monitor_interval_ms: 100,
330            max_memory_mb: 1024,
331            // Aligned with `DEFAULT_MAX_TOOL_WALL_CLOCK_SECS` (600). Previously 300,
332            // which conflicted with the harness wall-clock budget (600) and could
333            // truncate long agentic runs at 5 minutes, forcing "continue" nudges.
334            max_execution_time_secs: 600,
335            idle_timeout_ms: 5000, // 5 seconds idle timeout
336            idle_backoff_ms: 100,  // 100ms backoff during idle
337            max_idle_cycles: 10,   // 10 consecutive idle cycles before deep sleep
338        }
339    }
340}
341
342impl Default for ProfilingConfig {
343    fn default() -> Self {
344        Self {
345            enabled: false, // Disabled by default to avoid overhead
346            monitor_interval_ms: 100,
347            max_history_size: 1000,
348            auto_export_results: false,
349            export_file_path: "benchmark_results.json".to_string(),
350            enable_regression_testing: false,
351            max_regression_percent: 10.0,
352        }
353    }
354}
355
356impl OptimizationConfig {
357    /// Get optimized configuration for development
358    pub fn development() -> Self {
359        Self {
360            memory_pool: MemoryPoolConfig { enabled: true, ..Default::default() },
361            tool_registry: ToolRegistryConfig {
362                use_optimized_registry: true,
363                max_concurrent_tools: 2,
364                middleware_fail_open: false,
365                ..Default::default()
366            },
367            async_pipeline: AsyncPipelineConfig {
368                enable_batching: true,
369                enable_caching: true,
370                max_batch_size: 3,
371                ..Default::default()
372            },
373            llm_client: LLMClientConfig {
374                enable_connection_pooling: true,
375                enable_response_caching: true,
376                connection_pool_size: 2,
377                rate_limit_rps: 5.0,
378                ..Default::default()
379            },
380            agent_execution: AgentExecutionConfig {
381                use_optimized_loop: true,
382                enable_performance_prediction: false, // Disabled for dev
383                max_memory_mb: 512,
384                idle_timeout_ms: 2000, // Shorter idle timeout for development
385                idle_backoff_ms: 50,   // Shorter backoff for development
386                max_idle_cycles: 5,    // Fewer idle cycles for development
387                ..Default::default()
388            },
389            profiling: ProfilingConfig {
390                enabled: true, // Enabled for development
391                auto_export_results: true,
392                ..Default::default()
393            },
394            file_read_cache: FileReadCacheConfig::default(),
395            command_cache: CommandCacheConfig::default(),
396        }
397    }
398
399    /// Get optimized configuration for production
400    pub fn production() -> Self {
401        Self {
402            memory_pool: MemoryPoolConfig {
403                enabled: true,
404                max_string_pool_size: 128,
405                max_value_pool_size: 64,
406                max_vec_pool_size: 32,
407            },
408            tool_registry: ToolRegistryConfig {
409                use_optimized_registry: true,
410                max_concurrent_tools: 8,
411                hot_cache_size: 32,
412                default_timeout_secs: 300,
413                middleware_fail_open: false,
414            },
415            async_pipeline: AsyncPipelineConfig {
416                enable_batching: true,
417                enable_caching: true,
418                max_batch_size: 10,
419                batch_timeout_ms: 50,
420                cache_size: 200,
421            },
422            llm_client: LLMClientConfig {
423                enable_connection_pooling: true,
424                enable_response_caching: true,
425                enable_request_batching: true,
426                connection_pool_size: 8,
427                response_cache_size: 100,
428                cache_ttl_secs: 600,
429                rate_limit_rps: 20.0,
430                rate_limit_burst: 50,
431            },
432            agent_execution: AgentExecutionConfig {
433                use_optimized_loop: true,
434                enable_performance_prediction: true,
435                state_history_size: 2000,
436                resource_monitor_interval_ms: 50,
437                max_memory_mb: 2048,
438                max_execution_time_secs: 600,
439                idle_timeout_ms: 10000, // Longer idle timeout for production
440                idle_backoff_ms: 200,   // Longer backoff for production
441                max_idle_cycles: 20,    // More idle cycles for production
442            },
443            profiling: ProfilingConfig {
444                enabled: false, // Disabled in production unless needed
445                monitor_interval_ms: 1000,
446                max_history_size: 500,
447                auto_export_results: false,
448                export_file_path: "/var/log/vtcode/benchmark_results.json".to_string(),
449                enable_regression_testing: true,
450                max_regression_percent: 5.0,
451            },
452            file_read_cache: FileReadCacheConfig {
453                enabled: true,
454                min_size_bytes: crate::constants::optimization::FILE_READ_CACHE_PROD_MIN_SIZE_BYTES,
455                max_size_bytes: crate::constants::optimization::FILE_READ_CACHE_PROD_MAX_SIZE_BYTES,
456                ttl_secs: crate::constants::optimization::FILE_READ_CACHE_PROD_TTL_SECS,
457                max_entries: crate::constants::optimization::FILE_READ_CACHE_PROD_MAX_ENTRIES,
458                max_read_lines: crate::constants::optimization::DEFAULT_MAX_READ_LINES,
459            },
460            command_cache: CommandCacheConfig {
461                enabled: true,
462                ttl_ms: crate::constants::optimization::COMMAND_CACHE_PROD_TTL_MS,
463                max_entries: crate::constants::optimization::COMMAND_CACHE_PROD_MAX_ENTRIES,
464                allowlist: crate::constants::optimization::COMMAND_CACHE_PROD_ALLOWLIST
465                    .iter()
466                    .map(|s| s.to_string())
467                    .collect(),
468            },
469        }
470    }
471}