use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct V8EngineFlags {
pub turbo_optimization_level: u8,
pub turbo_profiling: bool,
pub max_old_space_mb: usize,
pub max_new_space_mb: usize,
pub gc_interval_ms: u64,
pub enable_sparkplug: bool,
pub enable_maglev: bool,
pub max_inline_depth: u32,
pub jit_enabled: bool,
pub optimize_for_size: u8,
pub code_range_size_mb: usize,
pub concurrent_gc: bool,
pub incremental_marking: bool,
pub max_executable_size_mb: usize,
}
impl Default for V8EngineFlags {
fn default() -> Self {
Self {
turbo_optimization_level: 3,
turbo_profiling: false,
max_old_space_mb: 256,
max_new_space_mb: 16,
gc_interval_ms: 500,
enable_sparkplug: true,
enable_maglev: true,
max_inline_depth: 10,
jit_enabled: true,
optimize_for_size: 0,
code_range_size_mb: 0,
concurrent_gc: true,
incremental_marking: true,
max_executable_size_mb: 128,
}
}
}
impl V8EngineFlags {
pub fn high_performance() -> Self {
Self {
turbo_optimization_level: 4, turbo_profiling: true, max_old_space_mb: 512, max_new_space_mb: 64, gc_interval_ms: 100, enable_sparkplug: true, enable_maglev: true, max_inline_depth: 15, jit_enabled: true, optimize_for_size: 0, code_range_size_mb: 256, concurrent_gc: true, incremental_marking: true, max_executable_size_mb: 256, }
}
pub fn balanced() -> Self {
Self {
turbo_optimization_level: 3,
turbo_profiling: false,
max_old_space_mb: 256,
max_new_space_mb: 32,
gc_interval_ms: 200,
enable_sparkplug: true,
enable_maglev: true,
max_inline_depth: 10,
jit_enabled: true,
optimize_for_size: 1,
code_range_size_mb: 128,
concurrent_gc: true,
incremental_marking: true,
max_executable_size_mb: 128,
}
}
pub fn low_memory() -> Self {
Self {
turbo_optimization_level: 2,
turbo_profiling: false,
max_old_space_mb: 128,
max_new_space_mb: 16,
gc_interval_ms: 100,
enable_sparkplug: true,
enable_maglev: false,
max_inline_depth: 5,
jit_enabled: true,
optimize_for_size: 2,
code_range_size_mb: 64,
concurrent_gc: false,
incremental_marking: false,
max_executable_size_mb: 64,
}
}
pub fn to_v8_flags(&self) -> Vec<String> {
let mut flags = Vec::new();
if self.jit_enabled {
flags.push("--turbofan".to_string());
}
flags.push(format!("--turbo_optimization_level={}", self.turbo_optimization_level));
flags.push(format!("--max_old_space_size={}", self.max_old_space_mb));
flags.push(format!("--max_new_space_size={}", self.max_new_space_mb));
if self.enable_sparkplug {
flags.push("--sparkplug".to_string());
}
if self.enable_maglev {
flags.push("--maglev".to_string());
}
flags.push(format!("--max_inline_depth={}", self.max_inline_depth));
if self.code_range_size_mb > 0 {
flags.push(format!("--code_range_size={}", self.code_range_size_mb));
}
if self.max_executable_size_mb > 0 {
flags.push(format!("--max_executable_size={}", self.max_executable_size_mb));
}
if self.concurrent_gc {
flags.push("--concurrent_gc".to_string());
}
if self.incremental_marking {
flags.push("--incremental_marking".to_string());
}
flags.push(format!("--gc_interval={}", self.gc_interval_ms));
if self.turbo_profiling {
flags.push("--turbo_profiling".to_string());
}
if self.optimize_for_size > 0 {
flags.push(format!("--optimize_for_size={}", self.optimize_for_size));
}
flags.push("--inline-js".to_string()); flags.push("--inline-wasm".to_string()); flags.push("--turbo_fast_math".to_string()); flags.push("--turbo_loop_peeling".to_string()); flags.push("--turbo_loop_unrolling".to_string()); flags.push("--turbo_loop_variable_scheduling".to_string()); flags
}
pub fn profile_name(&self) -> &str {
match (
self.turbo_optimization_level,
self.max_old_space_mb,
self.max_inline_depth,
) {
(4, 512..=usize::MAX, 15) => "high_performance",
(3, 256..=511, 10) => "balanced",
(_, 128..=255, _) => "low_memory",
_ => "custom",
}
}
pub fn estimated_memory_mb(&self) -> usize {
self.max_old_space_mb + self.max_new_space_mb + self.code_range_size_mb
}
}
#[derive(Debug)]
pub struct V8ConfigManager {
configs: HashMap<String, V8EngineFlags>,
}
impl V8ConfigManager {
pub fn new() -> Self {
let mut configs = HashMap::new();
configs.insert("default".to_string(), V8EngineFlags::default());
configs.insert("high_performance".to_string(), V8EngineFlags::high_performance());
configs.insert("balanced".to_string(), V8EngineFlags::balanced());
configs.insert("low_memory".to_string(), V8EngineFlags::low_memory());
Self { configs }
}
pub fn get(&self, name: &str) -> Option<&V8EngineFlags> {
self.configs.get(name)
}
pub fn add(&mut self, name: String, flags: V8EngineFlags) {
self.configs.insert(name, flags);
}
pub fn config_names(&self) -> Vec<&str> {
self.configs.keys().map(|k| k.as_str()).collect()
}
pub fn best_for_system(&self) -> &V8EngineFlags {
self.configs.get("high_performance").unwrap()
}
}
impl Default for V8ConfigManager {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_high_performance_config() {
let flags: _ = V8EngineFlags::high_performance();
assert_eq!(flags.turbo_optimization_level, 4);
assert!(flags.turbo_profiling);
assert_eq!(flags.max_old_space_mb, 512);
assert!(flags.jit_enabled);
}
#[test]
fn test_v8_flags_conversion() {
let flags: _ = V8EngineFlags::high_performance();
let v8_flags: _ = flags.to_v8_flags();
assert!(v8_flags.contains(&"--turbofan".to_string()));
assert!(v8_flags.iter().any(|f| f.contains("turbo_optimization_level=4")));
assert!(v8_flags.contains(&"--sparkplug".to_string()));
}
#[test]
fn test_config_manager() {
let manager: _ = V8ConfigManager::new();
assert!(manager.config_names().contains(&"high_performance"));
assert!(manager.get("high_performance").is_some());
}
#[test]
fn test_profile_name() {
let flags: _ = V8EngineFlags::high_performance();
assert_eq!(flags.profile_name(), "high_performance");
}
#[test]
fn test_estimated_memory() {
let flags: _ = V8EngineFlags::high_performance();
let mem: _ = flags.estimated_memory_mb();
assert_eq!(mem, 512 + 64 + 256); }
}