use super::{VirtualListLayoutMode, config::VirtualListInternalParams};
use crate::prelude::*;
use std::time::{Duration, Instant};
#[derive(Clone)]
pub struct AdaptiveItemPool {
available_panels: Vec<Panel>,
target_pool_size: usize,
max_pool_size: usize,
total_created: usize,
total_reused: usize,
total_requests: usize,
last_optimization: Instant,
optimization_interval: Duration,
pool_hit_rate_history: Vec<f64>,
efficiency_target: f64,
}
impl std::fmt::Debug for AdaptiveItemPool {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AdaptiveItemPool")
.field("available_panels", &format!("{} panels", self.available_panels.len()))
.field("target_pool_size", &self.target_pool_size)
.field("max_pool_size", &self.max_pool_size)
.field("total_created", &self.total_created)
.field("total_reused", &self.total_reused)
.field("hit_rate", &self.calculate_hit_rate())
.field("efficiency_score", &self.calculate_efficiency_score())
.finish()
}
}
impl AdaptiveItemPool {
pub fn new(_layout_mode: VirtualListLayoutMode, internal_params: &VirtualListInternalParams) -> Self {
let target_size = internal_params.pool_target_size;
Self {
available_panels: Vec::with_capacity(target_size),
target_pool_size: target_size,
max_pool_size: target_size * 2,
total_created: 0,
total_reused: 0,
total_requests: 0,
last_optimization: Instant::now(),
optimization_interval: Duration::from_secs(5),
pool_hit_rate_history: Vec::with_capacity(10),
efficiency_target: 0.8, }
}
pub fn get_or_create_item<F>(&mut self, _parent: &Panel, create_fn: F) -> Panel
where
F: FnOnce() -> Panel,
{
self.total_requests += 1;
if let Some(panel) = self.available_panels.pop() {
self.total_reused += 1;
panel.show(true);
panel
} else {
self.total_created += 1;
let new_panel = create_fn();
self.maybe_optimize_pool();
new_panel
}
}
pub fn return_item(&mut self, panel: Panel) {
if self.available_panels.len() < self.max_pool_size {
panel.show(false);
self.available_panels.push(panel);
} else {
panel.show(false);
}
}
fn maybe_optimize_pool(&mut self) {
let now = Instant::now();
if now.duration_since(self.last_optimization) < self.optimization_interval {
return;
}
self.last_optimization = now;
let current_hit_rate = self.calculate_hit_rate();
self.pool_hit_rate_history.push(current_hit_rate);
if self.pool_hit_rate_history.len() > 10 {
self.pool_hit_rate_history.remove(0);
}
let avg_hit_rate = self.pool_hit_rate_history.iter().sum::<f64>() / self.pool_hit_rate_history.len() as f64;
if avg_hit_rate < self.efficiency_target - 0.1 {
self.target_pool_size = (self.target_pool_size + 2).min(self.max_pool_size);
} else if avg_hit_rate > self.efficiency_target + 0.1 && self.target_pool_size > 4 {
self.target_pool_size = (self.target_pool_size - 1).max(4);
}
}
fn calculate_hit_rate(&self) -> f64 {
if self.total_requests == 0 {
return 0.0;
}
self.total_reused as f64 / self.total_requests as f64
}
fn calculate_efficiency_score(&self) -> f64 {
let hit_rate = self.calculate_hit_rate();
let size_efficiency = if self.max_pool_size > 0 {
1.0 - (self.available_panels.len() as f64 / self.max_pool_size as f64)
} else {
1.0
};
(hit_rate * 0.7) + (size_efficiency * 0.3)
}
pub fn clear_all(&mut self) {
for panel in &self.available_panels {
panel.show(false);
}
self.available_panels.clear();
self.pool_hit_rate_history.clear();
self.last_optimization = Instant::now();
}
pub fn get_pool_stats(&self) -> PoolStats {
PoolStats {
available_count: self.available_panels.len(),
active_count: self.total_created - self.available_panels.len(), target_size: self.target_pool_size,
max_size: self.max_pool_size,
total_created: self.total_created,
total_reused: self.total_reused,
total_requests: self.total_requests,
hit_rate: self.calculate_hit_rate(),
efficiency_score: self.calculate_efficiency_score(),
utilization: if self.target_pool_size > 0 {
self.available_panels.len() as f64 / self.target_pool_size as f64
} else {
0.0
},
}
}
}
pub struct PoolStats {
pub available_count: usize,
pub active_count: usize,
pub target_size: usize,
pub max_size: usize,
pub total_created: usize,
pub total_reused: usize,
pub total_requests: usize,
pub hit_rate: f64,
pub efficiency_score: f64,
pub utilization: f64,
}
impl PoolStats {
pub fn is_healthy(&self) -> bool {
self.hit_rate > 0.7 && self.utilization < 0.9 && self.efficiency_score > 0.6
}
pub fn performance_rating(&self) -> &'static str {
if self.efficiency_score > 0.8 {
"Excellent"
} else if self.efficiency_score > 0.6 {
"Good"
} else {
"Poor"
}
}
pub fn efficiency_score(&self) -> f64 {
self.efficiency_score
}
}