Caching
Das Zwischenspeichern von häufig angefragten Daten oder Berechnungsergebnissen, um wiederholte Anfragen schneller und günstiger zu beantworten.
Zwei zentrale Performance-Metriken – Latenz misst wie schnell, Throughput misst wie viel. Oft gibt es Trade-offs, je nach Use Case und Architektur.
Latenz und Throughput sind zwei zentrale Performance-Metriken. Sie messen verschiedene Dinge und stehen je nach Architektur, Last und Optimierung oft in einem Trade-off.
Die Definitionen:
Latenz (Latency):
"Wie lange dauert EINE Anfrage?"
→ Gemessen in Millisekunden (ms)
→ Wichtig für User Experience
Throughput:
"Wie viele Anfragen pro Sekunde?"
→ Gemessen in Requests/Second (RPS)
→ Wichtig für Kapazität
Beispiel:
| System | Latenz | Throughput | Use Case |
|---|---|---|---|
| Chat-API | niedriger Zielwert | moderater Durchsatz | Interaktiv |
| Batch-ML | höher tolerierbar | hoher Durchsatz | Hintergrund |
| Datenbank | workloadabhängig | workloadabhängig | Beides wichtig |
Ohne Batching:
Request 1: ──────► einzelne Verarbeitung
Request 2: ──────► einzelne Verarbeitung
Request 3: ──────► einzelne Verarbeitung
Latenz: niedriger, Throughput: begrenzt durch Overhead
Mit Batching:
Request 1: ─┐
Request 2: ─┼─────────► gemeinsame Verarbeitung
Request 3: ─┘
Latenz: kann steigen, Throughput kann steigen
import numpy as np
def analyze_latencies(latencies):
return {
"p50": np.percentile(latencies, 50), # Median
"p90": np.percentile(latencies, 90), # 90% schneller
"p95": np.percentile(latencies, 95), # 95% schneller
"p99": np.percentile(latencies, 99), # 99% schneller
"p999": np.percentile(latencies, 99.9), # Worst case
"mean": np.mean(latencies),
"max": np.max(latencies),
}
# Beispiel
latencies = observed_latencies_ms
# Percentiles zeigen Tail-Latency oft besser als der Durchschnitt
import time
import asyncio
async def benchmark_throughput(client, duration_seconds):
start = time.time()
request_count = 0
while time.time() - start < duration_seconds:
await client.request()
request_count += 1
elapsed = time.time() - start
throughput = request_count / elapsed
return f"{throughput:.2f} requests/second"
L = λ × W
L = Anzahl gleichzeitiger Requests im System
λ = Throughput (Requests/Sekunde)
W = Durchschnittliche Latenz (Sekunden)
Beispiel:
- Throughput: λ Requests/Sekunde
- Latenz: W Sekunden
- Gleichzeitige Requests: L = λ × W
| Ziel | Strategie |
|---|---|
| Niedrige Latenz | Caching, Edge Computing, weniger Hops prüfen |
| Hoher Throughput | Batching, Parallelisierung, Async prüfen |
| Beides | Horizontale Skalierung, effiziente Implementierung und Kapazitätsplanung |
# Ohne Batching: oft niedrigere Latenz, aber begrenzter Throughput
async def predict_single(model, input):
return model(input)
# Mit Batching: potenziell höhere Latenz, aber höherer Throughput
class BatchPredictor:
def __init__(self, model, batch_size, max_wait_ms):
self.model = model
self.batch_size = batch_size
self.max_wait = max_wait_ms / 1000
self.queue = []
async def predict(self, input):
future = asyncio.Future()
self.queue.append((input, future))
if len(self.queue) >= self.batch_size:
await self._process_batch()
else:
await asyncio.sleep(self.max_wait)
if self.queue:
await self._process_batch()
return await future
async def _process_batch(self):
batch = self.queue[:self.batch_size]
self.queue = self.queue[self.batch_size:]
inputs = [item[0] for item in batch]
results = self.model(inputs) # Batch inference
for (_, future), result in zip(batch, results):
future.set_result(result) Latenz ist wie die Fahrzeit eines einzelnen Autos von A nach B. Throughput ist wie viele Autos pro Stunde die Straße passieren. Eine Autobahn hat hohen Throughput aber nicht unbedingt niedrige Latenz (Stau!).
Latenz: Zeit für eine einzelne Operation (ms)
Throughput: Operationen pro Zeiteinheit (req/s)
Oft Trade-off: Batching erhöht Throughput, aber auch Latenz
Real-Time APIs
Niedrige Latenz ist oft wichtig für interaktive Anwendungen
Batch Processing
Hoher Throughput wichtiger als Latenz
ML Inference
Balance zwischen beiden für verschiedene Use Cases
Architektur
OLTP (Latenz) vs. OLAP (Throughput)
Kommt auf den Use Case an. Interaktive Apps priorisieren oft Latenz, Batch-Jobs eher Throughput. Häufig müssen beide Metriken mit unterschiedlichen Zielwerten betrachtet werden.
Batching kann Throughput erhöhen, weil weniger Overhead pro Request anfällt. Gleichzeitig kann es Latenz erhöhen, weil Requests auf einen Batch warten. Ob es sinnvoll ist, hängt von Use Case, SLA und Modellkosten ab.
P99 bedeutet: 99% der Requests sind schneller als dieser Wert. Percentile zeigen Ausreißer besser als der Durchschnitt. P50 ist der Median, P95/P99 zeigen Tail-Latency.