use std::sync::{Arc, Mutex, PoisonError};
use std::time::{Duration, Instant};
use crate::perf_gate::bootstrap::{bootstrap_agg_tok_s_ci, BootstrapCi};
use crate::perf_gate::drain::StreamMode;
use crate::perf_gate::metrics::{BandMetrics, RequestSample};
use crate::perf_gate::protocol::{BandConfig, ClientModel, Outcome, TokenizationBlock, REPLICATES};
use crate::perf_gate::window::{WindowController, WindowReport};
use super::client::ChatResponse;
use super::client::{ChatRequest, LlmClient, LlmClientError};
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct RequestExtra {
pub expected_tokens: Option<u32>,
pub prefill_ms: Option<f64>,
pub stream_mode: Option<StreamMode>,
}
#[must_use]
fn band_stream_mode(samples: &[RequestSample], extras: &[RequestExtra]) -> Option<StreamMode> {
let mut declared_live = false;
for (s, e) in samples.iter().zip(extras.iter()) {
if s.outcome != Outcome::Completed {
continue;
}
match e.stream_mode {
None => return None,
Some(StreamMode::Replayed) => return Some(StreamMode::Replayed),
Some(StreamMode::Live) => declared_live = true,
}
}
declared_live.then_some(StreamMode::Live)
}
#[derive(Debug, Clone)]
pub struct BandRun {
pub config: BandConfig,
pub client_model: ClientModel,
pub tokenization: TokenizationBlock,
pub metrics: BandMetrics,
pub window: WindowReport,
pub samples: Vec<RequestSample>,
pub extras: Vec<RequestExtra>,
pub stream_mode: Option<StreamMode>,
pub agg_ci: Option<BootstrapCi>,
pub warmup_completed: usize,
pub protocol_violations: Vec<String>,
}
impl BandRun {
#[must_use]
pub fn is_conformant(&self) -> bool {
self.protocol_violations.is_empty() && self.window.suspect.is_empty()
}
}
type Shared = Arc<Mutex<WindowController>>;
type Admitted = (usize, usize);
fn lock<T>(m: &Mutex<T>) -> std::sync::MutexGuard<'_, T> {
m.lock().unwrap_or_else(PoisonError::into_inner)
}
async fn warmup(
client: &LlmClient,
prompts: &[ChatRequest],
band: &BandConfig,
stream: bool,
) -> usize {
let per_worker = band.warmup_requests.div_ceil(band.concurrency).max(1);
let mut handles = Vec::with_capacity(band.concurrency);
for worker in 0..band.concurrency {
let client = client.clone();
let prompts = prompts.to_vec();
handles.push(tokio::spawn(async move {
let mut done = 0_usize;
for k in 0..per_worker {
let prompt = &prompts[(worker + k) % prompts.len()];
if issue(&client, prompt, stream).await.is_some() {
done += 1;
}
}
done
}));
}
let mut total = 0;
for h in handles {
total += h.await.unwrap_or(0);
}
total
}
struct Worker {
id: usize,
client: LlmClient,
prompts: Vec<ChatRequest>,
controller: Shared,
samples: Arc<Mutex<Vec<(RequestSample, RequestExtra)>>>,
timeout: Duration,
origin: Instant,
stream: bool,
}
struct Observed {
token_offsets: Vec<Duration>,
generated_tokens: u32,
prompt_tokens: u32,
prefill_ms: Option<f64>,
stream_mode: Option<StreamMode>,
}
fn observe_blocking(response: &ChatResponse) -> Observed {
let (generated_tokens, prompt_tokens) = response
.usage
.as_ref()
.map_or((0, 0), |u| (u.completion_tokens, u.prompt_tokens));
Observed {
token_offsets: Vec::new(),
generated_tokens,
prompt_tokens,
prefill_ms: None,
stream_mode: None,
}
}
async fn issue(client: &LlmClient, prompt: &ChatRequest, stream: bool) -> Option<Observed> {
if stream {
let streamed = client.chat_completion_stream(prompt).await.ok()?;
return Some(Observed {
token_offsets: streamed.token_timestamps,
generated_tokens: streamed.usage.completion_tokens,
prompt_tokens: streamed.usage.prompt_tokens,
prefill_ms: streamed.timings.and_then(|t| t.prompt_ms),
stream_mode: streamed.stream_mode,
});
}
let timed = client.send(prompt).await.ok()?;
Some(observe_blocking(&timed.response))
}
fn sample_from(
slot: Admitted,
worker: usize,
span: (f64, f64),
drained: bool,
observed: Option<&Observed>,
) -> RequestSample {
let (start_s, end_s) = span;
let (index, in_flight_at_start) = slot;
let Some(observed) = observed else {
return RequestSample {
index,
worker,
start_s,
end_s,
token_times_s: Vec::new(),
generated_tokens: 0,
prompt_tokens: 0,
outcome: Outcome::Failed,
in_flight_at_start,
drained,
};
};
RequestSample {
index,
worker,
start_s,
end_s,
token_times_s: observed
.token_offsets
.iter()
.map(|d| start_s + d.as_secs_f64())
.collect(),
generated_tokens: observed.generated_tokens,
prompt_tokens: observed.prompt_tokens,
outcome: Outcome::Completed,
in_flight_at_start,
drained,
}
}
async fn worker_loop(w: Worker) {
loop {
let admitted = {
let mut c = lock(&w.controller);
c.try_admit_with_in_flight(w.origin.elapsed().as_secs_f64())
};
let Some(slot) = admitted else { break };
let prompt = &w.prompts[slot.0 % w.prompts.len()];
let start_s = w.origin.elapsed().as_secs_f64();
let timed_out = tokio::time::timeout(w.timeout, issue(&w.client, prompt, w.stream)).await;
let end_s = w.origin.elapsed().as_secs_f64();
let drained = lock(&w.controller).complete(end_s);
let observed = match &timed_out {
Ok(observed) => observed.as_ref(),
Err(_elapsed) => None,
};
let mut sample = sample_from(slot, w.id, (start_s, end_s), drained, observed);
if timed_out.is_err() {
sample.outcome = Outcome::Timeout;
}
let extra = RequestExtra {
expected_tokens: prompt.max_tokens,
prefill_ms: observed.and_then(|o| o.prefill_ms),
stream_mode: observed.and_then(|o| o.stream_mode),
};
lock(&w.samples).push((sample, extra));
}
}
fn violations(
band: &BandConfig,
warmup_completed: usize,
m: &BandMetrics,
win: &WindowReport,
) -> Vec<String> {
let mut out = band.conformance_violations();
if warmup_completed < band.warmup_requests {
out.push(format!(
"§4.4.2 warmup completed {warmup_completed} of {} required requests",
band.warmup_requests
));
}
if m.completed < band.min_samples {
out.push(format!(
"§4.4.2 only {} of {} required sampled requests completed",
m.completed, band.min_samples
));
}
out.extend(win.suspect.iter().cloned());
out
}
pub async fn run_band(
client: &LlmClient,
prompts: &[ChatRequest],
band: &BandConfig,
tokenization: TokenizationBlock,
stream: bool,
) -> Result<BandRun, LlmClientError> {
if prompts.is_empty() {
return Err(LlmClientError::HealthCheckFailed(
"run_band: the prompt corpus is empty; §4.3 requires a fixed workload".to_string(),
));
}
tokenization
.validate()
.map_err(LlmClientError::HealthCheckFailed)?;
let warmup_completed = warmup(client, prompts, band, stream).await;
tokio::time::sleep(band.quiesce).await;
let controller: Shared = Arc::new(Mutex::new(WindowController::new(band)));
let samples: Arc<Mutex<Vec<(RequestSample, RequestExtra)>>> = Arc::new(Mutex::new(Vec::new()));
let origin = Instant::now();
let mut handles = Vec::with_capacity(band.concurrency);
for id in 0..band.concurrency {
handles.push(tokio::spawn(worker_loop(Worker {
id,
client: client.clone(),
prompts: prompts.to_vec(),
controller: Arc::clone(&controller),
samples: Arc::clone(&samples),
timeout: band.request_timeout,
origin,
stream,
})));
}
for h in handles {
let _ = h.await;
}
let window = lock(&controller).report();
let mut collected = std::mem::take(&mut *lock(&samples));
collected.sort_by_key(|(s, _)| s.index);
let (collected, extras): (Vec<RequestSample>, Vec<RequestExtra>) =
collected.into_iter().unzip();
let metrics = BandMetrics::from_samples(band.concurrency, &collected);
let agg_ci = bootstrap_agg_tok_s_ci(&collected, 0.95);
let protocol_violations = violations(band, warmup_completed, &metrics, &window);
let stream_mode = band_stream_mode(&collected, &extras);
Ok(BandRun {
config: band.clone(),
client_model: band.client_model,
tokenization,
metrics,
window,
samples: collected,
extras,
stream_mode,
agg_ci,
warmup_completed,
protocol_violations,
})
}
pub async fn run_cell(
client: &LlmClient,
prompts: &[ChatRequest],
band: &BandConfig,
tokenization: &TokenizationBlock,
stream: bool,
) -> Result<Vec<BandRun>, LlmClientError> {
let mut runs = Vec::with_capacity(REPLICATES);
for _ in 0..REPLICATES {
runs.push(run_band(client, prompts, band, tokenization.clone(), stream).await?);
}
Ok(runs)
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::atomic::{AtomicUsize, Ordering};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpListener;
const BODY: &str = concat!(
r#"{"id":"c","object":"chat.completion","created":0,"model":"m","#,
r#""choices":[{"index":0,"message":{"role":"assistant","content":"a b c"},"#,
r#""finish_reason":"length"}],"#,
r#""usage":{"prompt_tokens":512,"completion_tokens":128,"total_tokens":640}}"#
);
struct Probe {
url: String,
peak: Arc<AtomicUsize>,
served: Arc<AtomicUsize>,
}
async fn consume_request(sock: &mut tokio::net::TcpStream) {
let mut buf = vec![0_u8; 8192];
let mut seen = Vec::new();
while let Ok(n) = sock.read(&mut buf).await {
if n == 0 {
return;
}
seen.extend_from_slice(&buf[..n]);
let text = String::from_utf8_lossy(&seen).to_string();
let Some(head_end) = text.find("\r\n\r\n") else {
continue;
};
if seen.len() >= head_end + 4 + content_length(&text) {
return;
}
}
}
fn content_length(head: &str) -> usize {
head.to_lowercase()
.split("content-length:")
.nth(1)
.and_then(|t| t.split("\r\n").next())
.and_then(|t| t.trim().parse::<usize>().ok())
.unwrap_or(0)
}
async fn serve_one(mut sock: tokio::net::TcpStream, service_ms: u64, counters: Counters) {
let now = counters.in_flight.fetch_add(1, Ordering::SeqCst) + 1;
counters.peak.fetch_max(now, Ordering::SeqCst);
consume_request(&mut sock).await;
tokio::time::sleep(Duration::from_millis(service_ms)).await;
let resp = format!(
"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\
Content-Length: {}\r\nConnection: close\r\n\r\n{BODY}",
BODY.len()
);
let _ = sock.write_all(resp.as_bytes()).await;
let _ = sock.flush().await;
let _ = sock.shutdown().await;
counters.served.fetch_add(1, Ordering::SeqCst);
counters.in_flight.fetch_sub(1, Ordering::SeqCst);
}
#[derive(Clone)]
struct Counters {
in_flight: Arc<AtomicUsize>,
peak: Arc<AtomicUsize>,
served: Arc<AtomicUsize>,
}
async fn spawn_probe(service_ms: u64) -> Probe {
let listener = TcpListener::bind("127.0.0.1:0")
.await
.expect("bind loopback");
let addr = listener.local_addr().expect("local addr");
let counters = Counters {
in_flight: Arc::new(AtomicUsize::new(0)),
peak: Arc::new(AtomicUsize::new(0)),
served: Arc::new(AtomicUsize::new(0)),
};
let (peak, served) = (Arc::clone(&counters.peak), Arc::clone(&counters.served));
tokio::spawn(async move {
while let Ok((sock, _)) = listener.accept().await {
tokio::spawn(serve_one(sock, service_ms, counters.clone()));
}
});
Probe {
url: format!("http://{addr}"),
peak,
served,
}
}
async fn serve_sse(mut sock: tokio::net::TcpStream, tokens: usize, gap_ms: u64) {
consume_request(&mut sock).await;
let head = "HTTP/1.1 200 OK\r\nContent-Type: text/event-stream\r\n\
Cache-Control: no-cache\r\nConnection: close\r\n\r\n";
if sock.write_all(head.as_bytes()).await.is_err() {
return;
}
let first = "data: {\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\"}}],\
\"stream_mode\":\"live\"}\n\n";
if sock.write_all(first.as_bytes()).await.is_err() {
return;
}
for i in 0..tokens {
tokio::time::sleep(Duration::from_millis(gap_ms)).await;
let chunk = format!(
"data: {{\"choices\":[{{\"index\":0,\"delta\":{{\"content\":\"t{i} \"}}}}]}}\n\n"
);
if sock.write_all(chunk.as_bytes()).await.is_err() {
return;
}
let _ = sock.flush().await;
}
let terminal = format!(
"data: {{\"choices\":[{{\"index\":0,\"delta\":{{}},\"finish_reason\":\"length\"}}],\
\"usage\":{{\"prompt_tokens\":512,\"completion_tokens\":{SERVER_COMPLETION_TOKENS},\
\"total_tokens\":{}}},\"timings\":{{\"prompt_n\":512,\"prompt_ms\":40.0,\
\"predicted_n\":{SERVER_COMPLETION_TOKENS},\"predicted_ms\":200.0}}}}\n\n",
512 + SERVER_COMPLETION_TOKENS
);
let _ = sock.write_all(terminal.as_bytes()).await;
let _ = sock.write_all(b"data: [DONE]\n\n").await;
let _ = sock.flush().await;
let _ = sock.shutdown().await;
}
const SERVER_COMPLETION_TOKENS: u32 = 128;
async fn spawn_sse_probe(tokens: usize, gap_ms: u64) -> String {
let listener = TcpListener::bind("127.0.0.1:0")
.await
.expect("bind loopback");
let addr = listener.local_addr().expect("local addr");
tokio::spawn(async move {
while let Ok((sock, _)) = listener.accept().await {
tokio::spawn(serve_sse(sock, tokens, gap_ms));
}
});
format!("http://{addr}")
}
fn prompts() -> Vec<ChatRequest> {
vec![ChatRequest {
model: "m".to_string(),
messages: vec![super::super::client::ChatMessage {
role: super::super::client::Role::User,
content: "hello".to_string(),
}],
temperature: Some(0.0),
max_tokens: Some(128),
stream: Some(false),
seed: Some(0),
ignore_eos: Some(true),
stream_options: None,
}]
}
fn tokenization() -> TokenizationBlock {
TokenizationBlock::ServerUsage {
counts_special_tokens: false,
counts_prompt_echo: false,
}
}
fn tiny_band(c: usize, samples: usize) -> BandConfig {
BandConfig::relaxed(c, samples, Duration::ZERO, Duration::ZERO)
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn eight_workers_are_concurrent_over_real_http() {
let probe = spawn_probe(60).await;
let client = LlmClient::new(&probe.url, "m");
let band = tiny_band(8, 32);
let run = run_band(&client, &prompts(), &band, tokenization(), false)
.await
.expect("band runs");
let server_peak = probe.peak.load(Ordering::SeqCst);
let client_peak = run.window.client_peak_in_flight;
eprintln!(
"run_band c=8: server_peak={server_peak} client_peak={client_peak} \
requested={} completed={} window_ms={:.1} drain_ms={:.1} served={}",
run.window.requested,
run.metrics.completed,
run.window.window_ms,
run.window.drain_ms,
probe.served.load(Ordering::SeqCst)
);
assert_eq!(client_peak, 8, "the client must admit 8 at once");
assert!(
server_peak >= 4,
"the SERVER saw only {server_peak} concurrent connections; a client that \
says c=8 and is secretly sequential shows 1"
);
assert!(run.metrics.completed >= 32, "{:?}", run.metrics);
assert!(run.metrics.agg_tok_s > 0.0);
assert_eq!(run.metrics.timeouts, 0);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn c1_is_sequential_and_slower_for_the_same_work() {
let requests = 16;
let service_ms = 40;
let p1 = spawn_probe(service_ms).await;
let c1 = LlmClient::new(&p1.url, "m");
let t1 = Instant::now();
let r1 = run_band(
&c1,
&prompts(),
&tiny_band(1, requests),
tokenization(),
false,
)
.await
.expect("c=1 band runs");
let wall1 = t1.elapsed();
let p8 = spawn_probe(service_ms).await;
let c8 = LlmClient::new(&p8.url, "m");
let t8 = Instant::now();
let r8 = run_band(
&c8,
&prompts(),
&tiny_band(8, requests),
tokenization(),
false,
)
.await
.expect("c=8 band runs");
let wall8 = t8.elapsed();
let speedup = wall1.as_secs_f64() / wall8.as_secs_f64();
eprintln!(
"same {requests} requests: c=1 wall={wall1:?} server_peak={} | \
c=8 wall={wall8:?} server_peak={} | speedup={speedup:.2}x",
p1.peak.load(Ordering::SeqCst),
p8.peak.load(Ordering::SeqCst)
);
assert_eq!(p1.peak.load(Ordering::SeqCst), 1, "c=1 must never overlap");
assert_eq!(r1.window.client_peak_in_flight, 1);
assert!(r8.window.client_peak_in_flight > 1);
assert!(
speedup > 2.0,
"c=8 must beat c=1 on the same work; got {speedup:.2}x \
(c=1 {wall1:?}, c=8 {wall8:?})"
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn ttft_and_itl_are_recovered_from_a_real_sse_stream() {
let url = spawn_sse_probe(6, 25).await;
let client = LlmClient::new(&url, "m");
let run = run_band(&client, &prompts(), &tiny_band(2, 8), tokenization(), true)
.await
.expect("band runs");
eprintln!(
"sse band: ttft_p50={:.1}ms ttft_p95={:.1}ms itl_p50={:.1}ms itl_p95={:.1}ms \
decode={:.1}tok/s completed={}",
run.metrics.ttft_p50_ms,
run.metrics.ttft_p95_ms,
run.metrics.itl_p50_ms,
run.metrics.itl_p95_ms,
run.metrics.decode_tok_s,
run.metrics.completed
);
assert!(run.metrics.completed >= 8, "{:?}", run.metrics);
assert!(
(10.0..200.0).contains(&run.metrics.ttft_p50_ms),
"ttft_p50={} ms, expected ~25",
run.metrics.ttft_p50_ms
);
assert!(
(10.0..200.0).contains(&run.metrics.itl_p50_ms),
"itl_p50={} ms, expected ~25",
run.metrics.itl_p50_ms
);
assert!(run.metrics.decode_tok_s > 0.0);
let pooled: usize = run.samples.iter().map(|s| s.itl_gaps_ms().len()).sum();
assert_eq!(
pooled,
5 * run.samples.len(),
"every gap must be pooled, not one summary per request"
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn a_relaxed_band_reports_its_own_non_conformance() {
let probe = spawn_probe(5).await;
let client = LlmClient::new(&probe.url, "m");
let run = run_band(&client, &prompts(), &tiny_band(2, 8), tokenization(), false)
.await
.expect("band runs");
assert!(!run.is_conformant());
assert!(
run.protocol_violations
.iter()
.any(|v| v.contains("min_wall_clock")),
"{:?}",
run.protocol_violations
);
assert!(
run.protocol_violations
.iter()
.any(|v| v.contains("quiesce")),
"{:?}",
run.protocol_violations
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn drain_ms_and_window_ms_are_produced() {
let probe = spawn_probe(30).await;
let client = LlmClient::new(&probe.url, "m");
let run = run_band(
&client,
&prompts(),
&tiny_band(4, 14),
tokenization(),
false,
)
.await
.expect("band runs");
assert!(run.window.window_ms > 0.0, "{:?}", run.window);
assert!(run.window.drain_ms >= 0.0, "{:?}", run.window);
assert!(run.window.drain_ms > 0.0, "{:?}", run.window);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn an_invalid_tokenization_block_refuses_the_run() {
let probe = spawn_probe(1).await;
let client = LlmClient::new(&probe.url, "m");
let bad = TokenizationBlock::ClientTokenizer {
tokenizer_sha256: "deadbeef".to_string(),
counts_special_tokens: true,
counts_prompt_echo: false,
};
let r = run_band(&client, &prompts(), &tiny_band(1, 1), bad, false).await;
assert!(
r.is_err(),
"a run must not start without a valid §4.4.6 block"
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn an_empty_prompt_corpus_refuses_the_run() {
let probe = spawn_probe(1).await;
let client = LlmClient::new(&probe.url, "m");
let r = run_band(&client, &[], &tiny_band(1, 1), tokenization(), false).await;
assert!(r.is_err());
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn the_run_carries_samples_and_a_reproducible_interval() {
let probe = spawn_probe(5).await;
let client = LlmClient::new(&probe.url, "m");
let run = run_band(
&client,
&prompts(),
&tiny_band(4, 24),
tokenization(),
false,
)
.await
.expect("band runs");
assert_eq!(run.samples.len(), run.window.requested);
assert!(run.samples.iter().any(|s| s.in_flight_at_start > 1));
let ci = run.agg_ci.as_ref().expect("n >= 2");
assert_eq!(ci.seed, 2026);
assert_eq!(ci.resamples, 10_000);
assert_eq!(ci.resampling_unit, "whole_request");
let again = bootstrap_agg_tok_s_ci(&run.samples, 0.95).expect("n >= 2");
assert_eq!(&again, ci, "the interval must re-derive from the samples");
}
fn declared(
index: usize,
outcome: Outcome,
mode: Option<StreamMode>,
) -> (RequestSample, RequestExtra) {
(
RequestSample {
index,
worker: 0,
start_s: 0.0,
end_s: 1.0,
token_times_s: Vec::new(),
generated_tokens: 128,
prompt_tokens: 512,
outcome,
in_flight_at_start: 1,
drained: false,
},
RequestExtra {
expected_tokens: Some(128),
prefill_ms: None,
stream_mode: mode,
},
)
}
fn band_mode_of(rows: Vec<(RequestSample, RequestExtra)>) -> Option<StreamMode> {
let (samples, extras): (Vec<_>, Vec<_>) = rows.into_iter().unzip();
band_stream_mode(&samples, &extras)
}
#[test]
fn a_band_whose_every_request_declared_live_is_live() {
let rows = (0..4)
.map(|i| declared(i, Outcome::Completed, Some(StreamMode::Live)))
.collect();
assert_eq!(band_mode_of(rows), Some(StreamMode::Live));
}
#[test]
fn one_replayed_request_makes_the_band_replayed() {
let mut rows: Vec<_> = (0..4)
.map(|i| declared(i, Outcome::Completed, Some(StreamMode::Live)))
.collect();
rows[2] = declared(2, Outcome::Completed, Some(StreamMode::Replayed));
assert_eq!(band_mode_of(rows), Some(StreamMode::Replayed));
}
#[test]
fn one_undeclared_request_makes_the_band_undeclared() {
let mut rows: Vec<_> = (0..4)
.map(|i| declared(i, Outcome::Completed, Some(StreamMode::Live)))
.collect();
rows[1] = declared(1, Outcome::Completed, None);
assert_eq!(band_mode_of(rows), None);
}
#[test]
fn a_failed_requests_absent_declaration_does_not_undeclare_the_band() {
let rows = vec![
declared(0, Outcome::Completed, Some(StreamMode::Live)),
declared(1, Outcome::Failed, None),
declared(2, Outcome::Timeout, None),
declared(3, Outcome::Completed, Some(StreamMode::Live)),
];
assert_eq!(band_mode_of(rows), Some(StreamMode::Live));
}
#[test]
fn a_band_with_no_completed_request_declares_nothing() {
let rows = vec![declared(0, Outcome::Failed, Some(StreamMode::Live))];
assert_eq!(band_mode_of(rows), None);
assert_eq!(band_mode_of(Vec::new()), None);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn the_band_records_what_the_server_declared() {
let url = spawn_sse_probe(6, 5).await;
let client = LlmClient::new(&url, "m");
let run = run_band(&client, &prompts(), &tiny_band(2, 8), tokenization(), true)
.await
.expect("band runs");
assert_eq!(run.stream_mode, Some(StreamMode::Live));
assert_eq!(run.extras.len(), run.samples.len());
let completed: Vec<&RequestExtra> = run
.samples
.iter()
.zip(run.extras.iter())
.filter(|(s, _)| s.outcome == Outcome::Completed)
.map(|(_, e)| e)
.collect();
assert!(!completed.is_empty(), "{:?}", run.metrics);
for e in completed {
assert_eq!(e.expected_tokens, Some(128), "PP-28: the issued n_predict");
assert_eq!(e.prefill_ms, Some(40.0), "§3: the SERVER's prompt_ms");
assert_eq!(e.stream_mode, Some(StreamMode::Live));
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn decode_uses_the_server_count_not_the_chunk_count() {
let url = spawn_sse_probe(6, 5).await;
let client = LlmClient::new(&url, "m");
let run = run_band(&client, &prompts(), &tiny_band(2, 8), tokenization(), true)
.await
.expect("band runs");
let counts: Vec<u32> = run
.samples
.iter()
.filter(|s| s.outcome == Outcome::Completed)
.map(|s| s.generated_tokens)
.collect();
assert!(!counts.is_empty(), "{:?}", run.metrics);
for n in counts {
assert_eq!(
n, SERVER_COMPLETION_TOKENS,
"the server declared {SERVER_COMPLETION_TOKENS} completion tokens; a frame count \
would report 6"
);
}
for s in run
.samples
.iter()
.filter(|s| s.outcome == Outcome::Completed)
{
assert_eq!(
s.token_times_s.len(),
6,
"six frames were actually observed"
);
assert_eq!(
s.prompt_tokens, 512,
"§3: prompt_tokens is the server's too"
);
}
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn a_stream_without_usage_fails_the_request_rather_than_being_counted() {
async fn serve_usageless(mut sock: tokio::net::TcpStream) {
consume_request(&mut sock).await;
let head = "HTTP/1.1 200 OK\r\nContent-Type: text/event-stream\r\n\
Connection: close\r\n\r\n";
let _ = sock.write_all(head.as_bytes()).await;
let _ = sock
.write_all(
b"data: {\"choices\":[{\"index\":0,\"delta\":{\"content\":\"a \"}}]}\n\n",
)
.await;
let _ = sock.write_all(b"data: [DONE]\n\n").await;
let _ = sock.flush().await;
let _ = sock.shutdown().await;
}
let listener = TcpListener::bind("127.0.0.1:0")
.await
.expect("bind loopback");
let addr = listener.local_addr().expect("local addr");
tokio::spawn(async move {
while let Ok((sock, _)) = listener.accept().await {
tokio::spawn(serve_usageless(sock));
}
});
let client = LlmClient::new(&format!("http://{addr}"), "m");
let run = run_band(&client, &prompts(), &tiny_band(1, 4), tokenization(), true)
.await
.expect("the band still runs; the REQUESTS fail");
assert_eq!(run.metrics.completed, 0, "{:?}", run.metrics);
assert!(run.metrics.errors > 0, "{:?}", run.metrics);
assert_eq!(run.stream_mode, None, "no completed request declared one");
}
}