docs: v4 final results, error analysis, and updated journey

Add v4 sweep results and post-mortem analysis showing:

- direct-to-D path: 54.3% (1P7D) / 58.0% (2P6D) of requests now use
  KVC cleanly. P50=0.5s and TTFT P50=0.043s; this path beats baseline
  8DP across the board (P50 -24%, TTFT P50 -54%, TTFT P90 -79%).

- Overall vs baseline (errors+truncated excluded):
  v4 2P6D P50=0.85s vs baseline 0.66s (28% slower).
  Reason is not errors -- 35% of requests still hit
  fallback-large-append-session-cap, where capacity-based
  cap = usable_tokens / target_tokens evaluates to 1-2 (not 16)
  for large agentic inputs.

- 9-10% errors on KVC variants are mooncake TCP transfer timeouts,
  not SGLang logic bugs. Prefill log shows
  "Failed to send kv chunk ... 32s timeout ... session not alive".
  Errors concentrate in turn>=31 (large inputs) after run >44.8%.

Track:
- docs/KVC_DEBUG_JOURNEY_V1_TO_V4.md: append v4 results table,
  per-mode breakdown, and error root cause.
- scripts/analysis/{analyze_v3,analyze_v4,analyze_errors,compare_no_error}.py
- outputs/qwen3-30b-tp1-v{3,4}*/exp*_summary.json (force-added,
  small JSON; metrics.jsonl excluded due to size).
- outputs/qwen3-30b-tp1-v{3,4}*/sweep_results.txt

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
kzlin
2026-04-28 23:34:01 +08:00
parent c9d350b372
commit 74194e660a
11 changed files with 1162 additions and 3 deletions

View File

@@ -0,0 +1,52 @@
#!/usr/bin/env python3
"""V4 results analysis: errors, execution modes, latency by mode."""
import json
import numpy as np
from pathlib import Path
from collections import Counter
BASE = Path(__file__).parent
def load_rows(jsonl_path):
rows = []
with open(jsonl_path) as f:
for line in f:
rows.append(json.loads(line))
return rows
for name, path in [
("Exp1 1P7D cap=16", BASE / "exp1_1p7d_kvc_cap16_metrics.jsonl"),
("Exp2 2P6D cap=16", BASE / "exp2_2p6d_kvc_cap16_metrics.jsonl"),
]:
rows = load_rows(path)
print(f"\n========== {name} ==========")
ok = [r for r in rows if r.get("error") is None]
err = [r for r in rows if r.get("error") is not None]
print(f"Total: {len(rows)}, OK: {len(ok)}, Errors: {len(err)}")
# Errors finish_reason
if err:
finish_reasons = Counter()
for r in err:
fr = str(r.get("finish_reason") or r.get("error") or "?")
# Truncate long messages
short = fr[:120]
finish_reasons[short] += 1
print(f"\nError finish_reasons (top 5):")
for fr, cnt in finish_reasons.most_common(5):
print(f" {cnt}x: {fr}")
# Execution mode latency breakdown
modes = Counter(r["execution_mode"] for r in ok)
print(f"\nTop execution modes by latency:")
print(f"{'mode':<55}{'n':<8}{'%':<8}{'P50 lat':<10}{'P90 lat':<10}{'TTFT P50':<10}")
for mode, count in modes.most_common(8):
mode_rows = [r for r in ok if r["execution_mode"] == mode]
lats = [r["latency_s"] for r in mode_rows]
ttfts = [r["ttft_s"] for r in mode_rows]
print(f" {mode:<53}{count:<8}{count/len(ok)*100:>5.1f}% {np.percentile(lats,50):>7.3f}s {np.percentile(lats,90):>7.3f}s {np.percentile(ttfts,50):>7.3f}s")
# Per-D load
per_d = Counter(r.get("assigned_decode_node", "?") for r in ok)
print(f"\nPer-D load: max/min ratio = {max(per_d.values())/max(min(per_d.values()),1):.2f}x")
print(f" {dict(per_d.most_common())}")