-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplot.py
More file actions
63 lines (55 loc) · 2.69 KB
/
Copy pathplot.py
File metadata and controls
63 lines (55 loc) · 2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
"""Plot the throughput-vs-latency tradeoff from load_test.py results.
Two panels (never a dual-axis chart): throughput and latency share the x-axis
(concurrency) but each gets its own y-scale in its own panel.
"""
import matplotlib.pyplot as plt
# --- measured on a 4 GB RTX 3050, qwen2.5:1.5b via Ollama (from load_test.py) ---
concurrency = [1, 4, 8]
throughput = [84.0, 113.4, 105.0] # tokens/s
p50 = [0.53, 1.35, 3.34] # seconds
p95 = [0.75, 1.82, 3.89]
p99 = [0.77, 1.87, 4.02]
INK, MUTED, GRID = "#1f2937", "#6b7280", "#e5e7eb"
TEAL = "#0f9d8f"
# latency percentiles = an ORDERED magnitude -> one hue, light->dark (sequential)
RED_LIGHT, RED_MID, RED_DARK = "#fca5a5", "#ef4444", "#b91c1c"
plt.rcParams.update({
"figure.facecolor": "white", "axes.facecolor": "white",
"axes.edgecolor": MUTED, "axes.labelcolor": INK, "text.color": INK,
"xtick.color": MUTED, "ytick.color": MUTED, "font.size": 12,
"axes.spines.top": False, "axes.spines.right": False,
})
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(13, 5.2))
fig.suptitle("Serving tradeoff — Qwen2.5-1.5B on a 4 GB RTX 3050 (Ollama)",
fontsize=15, fontweight="bold", color=INK, y=0.99)
# --- panel 1: throughput ---
ax1.plot(concurrency, throughput, "-o", color=TEAL, linewidth=2.4, markersize=9)
ax1.set_title("Throughput peaks, then drops", fontsize=13, color=INK, pad=10)
ax1.set_xlabel("concurrency (simultaneous requests)")
ax1.set_ylabel("throughput (tokens/s)")
ax1.set_xticks(concurrency)
ax1.grid(True, color=GRID, linewidth=1)
ax1.set_axisbelow(True)
ax1.set_ylim(0, 130)
# annotate the peak
ax1.annotate("peak: 113 t/s @ c=4", xy=(4, 113.4), xytext=(4.3, 70),
color=INK, fontsize=11,
arrowprops=dict(arrowstyle="->", color=MUTED))
for x, y in zip(concurrency, throughput):
ax1.annotate(f"{y:.0f}", (x, y), textcoords="offset points",
xytext=(0, 10), ha="center", fontsize=10, color=MUTED)
# --- panel 2: latency (sequential ramp p50<p95<p99) ---
ax2.plot(concurrency, p50, "-o", color=RED_LIGHT, linewidth=2.2, markersize=8, label="p50")
ax2.plot(concurrency, p95, "-o", color=RED_MID, linewidth=2.2, markersize=8, label="p95")
ax2.plot(concurrency, p99, "-o", color=RED_DARK, linewidth=2.4, markersize=9, label="p99")
ax2.set_title("...but latency explodes", fontsize=13, color=INK, pad=10)
ax2.set_xlabel("concurrency (simultaneous requests)")
ax2.set_ylabel("latency (seconds)")
ax2.set_xticks(concurrency)
ax2.grid(True, color=GRID, linewidth=1)
ax2.set_axisbelow(True)
ax2.set_ylim(0, 4.4)
ax2.legend(frameon=False, loc="upper left")
fig.tight_layout(rect=[0, 0, 1, 0.96])
fig.savefig("tradeoff.png", dpi=150, bbox_inches="tight")
print("saved tradeoff.png")