#[derive(Debug, Clone)]
pub struct BatchScalingMeasurement {
pub batch_size: usize,
pub total_latency_ms: f64,
pub per_request_latency_ms: f64,
pub throughput_rps: f64,
}
#[derive(Debug, Clone)]
pub struct BatchScalingAnalysis {
pub measurements: Vec<BatchScalingMeasurement>,
pub scaling_efficiency: f64,
pub is_linear: bool,
pub target_efficiency: f64,
pub meets_qa018: bool,
}
impl BatchScalingAnalysis {
const DEFAULT_TARGET: f64 = 0.70;
pub fn analyze(measurements: &[BatchScalingMeasurement]) -> Self {
Self::analyze_with_target(measurements, Self::DEFAULT_TARGET)
}
pub fn analyze_with_target(
measurements: &[BatchScalingMeasurement],
target_efficiency: f64,
) -> Self {
if measurements.is_empty() {
return Self {
measurements: Vec::new(),
scaling_efficiency: 0.0,
is_linear: false,
target_efficiency,
meets_qa018: false,
};
}
let batch_1 = measurements.iter().find(|m| m.batch_size == 1);
let batch_8 = measurements.iter().find(|m| m.batch_size == 8);
let scaling_efficiency = match (batch_1, batch_8) {
(Some(b1), Some(b8)) if b1.throughput_rps > 0.0 => {
(b8.throughput_rps / b1.throughput_rps) / 8.0
},
_ => {
if measurements.len() < 2 {
0.0
} else {
let first = &measurements[0];
let last = &measurements[measurements.len() - 1];
let batch_ratio = last.batch_size as f64 / first.batch_size as f64;
let throughput_ratio = last.throughput_rps / first.throughput_rps;
throughput_ratio / batch_ratio
}
},
};
let is_linear = scaling_efficiency >= 0.7;
let meets_qa018 = scaling_efficiency >= target_efficiency;
Self {
measurements: measurements.to_vec(),
scaling_efficiency,
is_linear,
target_efficiency,
meets_qa018,
}
}
}
#[derive(Debug, Clone)]
pub struct BatchThroughputRegression {
pub slope: f64,
pub intercept: f64,
pub r_squared: f64,
pub good_fit: bool,
}
impl BatchThroughputRegression {
pub fn fit(measurements: &[BatchScalingMeasurement]) -> Self {
if measurements.len() < 2 {
return Self {
slope: 0.0,
intercept: 0.0,
r_squared: 0.0,
good_fit: false,
};
}
let n = measurements.len() as f64;
let sum_x: f64 = measurements.iter().map(|m| m.batch_size as f64).sum();
let sum_y: f64 = measurements.iter().map(|m| m.throughput_rps).sum();
let sum_xy: f64 = measurements
.iter()
.map(|m| m.batch_size as f64 * m.throughput_rps)
.sum();
let sum_xx: f64 = measurements
.iter()
.map(|m| (m.batch_size as f64).powi(2))
.sum();
let slope = (n * sum_xy - sum_x * sum_y) / (n * sum_xx - sum_x * sum_x);
let intercept = (sum_y - slope * sum_x) / n;
let mean_y = sum_y / n;
let ss_tot: f64 = measurements
.iter()
.map(|m| (m.throughput_rps - mean_y).powi(2))
.sum();
let ss_res: f64 = measurements
.iter()
.map(|m| (m.throughput_rps - (slope * m.batch_size as f64 + intercept)).powi(2))
.sum();
let r_squared = if ss_tot > 0.0 {
1.0 - ss_res / ss_tot
} else {
0.0
};
Self {
slope,
intercept,
r_squared,
good_fit: r_squared >= 0.8,
}
}
}
#[test]
fn test_imp_172a_batch_scaling_measurement() {
let linear = vec![
BatchScalingMeasurement {
batch_size: 1,
total_latency_ms: 100.0,
per_request_latency_ms: 100.0,
throughput_rps: 10.0,
},
BatchScalingMeasurement {
batch_size: 2,
total_latency_ms: 110.0,
per_request_latency_ms: 55.0,
throughput_rps: 18.0,
},
BatchScalingMeasurement {
batch_size: 4,
total_latency_ms: 130.0,
per_request_latency_ms: 32.5,
throughput_rps: 31.0,
},
BatchScalingMeasurement {
batch_size: 8,
total_latency_ms: 170.0,
per_request_latency_ms: 21.25,
throughput_rps: 47.0,
},
];
let analysis = BatchScalingAnalysis::analyze(&linear);
assert!(
analysis.scaling_efficiency > 0.5,
"IMP-172a: Should have reasonable scaling"
);
println!("\nIMP-172a: Batch Scaling Measurement:");
println!(
" Batch sizes: {:?}",
linear.iter().map(|m| m.batch_size).collect::<Vec<_>>()
);
println!(
" Throughputs: {:?}",
linear.iter().map(|m| m.throughput_rps).collect::<Vec<_>>()
);
println!(
" Scaling efficiency: {:.1}%",
analysis.scaling_efficiency * 100.0
);
println!(
" QA-018: {}",
if analysis.meets_qa018 { "PASS" } else { "FAIL" }
);
}
#[test]
fn test_imp_172b_batch_regression() {
let perfect = vec![
BatchScalingMeasurement {
batch_size: 1,
total_latency_ms: 100.0,
per_request_latency_ms: 100.0,
throughput_rps: 10.0,
},
BatchScalingMeasurement {
batch_size: 2,
total_latency_ms: 100.0,
per_request_latency_ms: 50.0,
throughput_rps: 20.0,
},
BatchScalingMeasurement {
batch_size: 4,
total_latency_ms: 100.0,
per_request_latency_ms: 25.0,
throughput_rps: 40.0,
},
BatchScalingMeasurement {
batch_size: 8,
total_latency_ms: 100.0,
per_request_latency_ms: 12.5,
throughput_rps: 80.0,
},
];
let regression = BatchThroughputRegression::fit(&perfect);
assert!(
regression.r_squared > 0.99,
"IMP-172b: Perfect scaling should have R² > 0.99"
);
assert!(
regression.slope > 9.0,
"IMP-172b: Perfect scaling slope should be ~10"
);
let sublinear = vec![
BatchScalingMeasurement {
batch_size: 1,
total_latency_ms: 100.0,
per_request_latency_ms: 100.0,
throughput_rps: 10.0,
},
BatchScalingMeasurement {
batch_size: 2,
total_latency_ms: 150.0,
per_request_latency_ms: 75.0,
throughput_rps: 13.0,
},
BatchScalingMeasurement {
batch_size: 4,
total_latency_ms: 250.0,
per_request_latency_ms: 62.5,
throughput_rps: 16.0,
},
BatchScalingMeasurement {
batch_size: 8,
total_latency_ms: 500.0,
per_request_latency_ms: 62.5,
throughput_rps: 16.0,
},
];
let sublinear_regression = BatchThroughputRegression::fit(&sublinear);
assert!(
sublinear_regression.r_squared < regression.r_squared,
"IMP-172b: Sublinear should have lower R²"
);
println!("\nIMP-172b: Batch Throughput Regression:");
println!(
" Perfect: slope={:.2}, intercept={:.2}, R²={:.4}",
regression.slope, regression.intercept, regression.r_squared
);
println!(
" Sublinear: slope={:.2}, intercept={:.2}, R²={:.4}",
sublinear_regression.slope, sublinear_regression.intercept, sublinear_regression.r_squared
);
}
#[test]
fn test_imp_172c_efficiency_thresholds() {
let good = vec![
BatchScalingMeasurement {
batch_size: 1,
total_latency_ms: 100.0,
per_request_latency_ms: 100.0,
throughput_rps: 10.0,
},
BatchScalingMeasurement {
batch_size: 8,
total_latency_ms: 125.0,
per_request_latency_ms: 15.6,
throughput_rps: 64.0,
}, ];
let good_analysis = BatchScalingAnalysis::analyze(&good);
assert!(
good_analysis.meets_qa018,
"IMP-172c: 80% efficiency should meet QA-018"
);
assert!(
good_analysis.is_linear,
"IMP-172c: 80% efficiency should be considered linear"
);
let poor = vec![
BatchScalingMeasurement {
batch_size: 1,
total_latency_ms: 100.0,
per_request_latency_ms: 100.0,
throughput_rps: 10.0,
},
BatchScalingMeasurement {
batch_size: 8,
total_latency_ms: 250.0,
per_request_latency_ms: 31.25,
throughput_rps: 32.0,
}, ];
let poor_analysis = BatchScalingAnalysis::analyze(&poor);
assert!(
!poor_analysis.meets_qa018,
"IMP-172c: 40% efficiency should not meet QA-018"
);
assert!(
!poor_analysis.is_linear,
"IMP-172c: 40% efficiency should not be considered linear"
);
println!("\nIMP-172c: Efficiency Thresholds:");
println!(
" Good: efficiency={:.1}%, QA-018={}",
good_analysis.scaling_efficiency * 100.0,
good_analysis.meets_qa018
);
println!(
" Poor: efficiency={:.1}%, QA-018={}",
poor_analysis.scaling_efficiency * 100.0,
poor_analysis.meets_qa018
);
}
#[test]
#[ignore = "Requires running llama.cpp server on port 8082"]
fn test_imp_172d_realworld_batch_scaling() {
let client = ModelHttpClient::with_timeout(120);
let mut measurements = Vec::new();
for batch_size in [1, 2, 4, 8] {
let prompt = "Hello, ".to_string();
let start = std::time::Instant::now();
let mut successful = 0;
for _ in 0..batch_size {
let request = CompletionRequest {
model: "default".to_string(),
prompt: prompt.clone(),
max_tokens: 10,
temperature: Some(0.0),
stream: false,
};
if client
.llamacpp_completion("http://127.0.0.1:8082", &request)
.is_ok()
{
successful += 1;
}
}
if successful == batch_size {
let elapsed = start.elapsed().as_secs_f64() * 1000.0;
measurements.push(BatchScalingMeasurement {
batch_size,
total_latency_ms: elapsed,
per_request_latency_ms: elapsed / batch_size as f64,
throughput_rps: batch_size as f64 / (elapsed / 1000.0),
});
}
}
if measurements.len() < 2 {
println!("IMP-172d: Not enough measurements");
return;
}
let analysis = BatchScalingAnalysis::analyze(&measurements);
let regression = BatchThroughputRegression::fit(&measurements);
println!("\nIMP-172d: Real-World Batch Scaling:");
for m in &measurements {
println!(
" batch={}: {:.1}ms total, {:.1}ms/req, {:.1} req/s",
m.batch_size, m.total_latency_ms, m.per_request_latency_ms, m.throughput_rps
);
}
println!(
" Scaling efficiency: {:.1}%",
analysis.scaling_efficiency * 100.0
);
println!(" Regression R²: {:.4}", regression.r_squared);
println!(
" QA-018 (linear scaling): {}",
if analysis.meets_qa018 { "PASS" } else { "FAIL" }
);
}