Skip to main content

A profiling tool for LLM inference servers: measure, diagnose, and visualize performance bottlenecks.

Project description

Inference Profiler

A profiling tool for LLM inference servers — the perf / PyTorch Profiler equivalent for serving. Point it at any OpenAI-compatible endpoint (vLLM, SGLang, TensorRT-LLM, TGI, llama.cpp server, …) and it measures where time goes, diagnoses bottlenecks, and renders a self-contained HTML report.

Everything runs locally. No cloud backend, no auth, no telemetry.

Why

Engineers usually know latency is bad, but not why. Inference Profiler answers:

  • Why is TTFT high — prefill compute, or requests stuck in the scheduler queue?
  • Is batching actually working, or is the GPU idle between requests?
  • Where is the throughput/latency knee as concurrency grows?
  • Are a few long prompts ruining tail latency for everyone?
  • Is the server compute-saturated, or starved for work?

Install

pip install inference-profiler          # core
pip install "inference-profiler[gpu]"   # + NVML GPU metrics (NVIDIA)

Quick start

inference-profiler profile \
    --endpoint http://localhost:8000/v1 \
    --model llama3 \
    --requests 500 \
    --concurrency 32 \
    --stream

Console output shows per-stage latency/throughput, findings, and an ASCII waterfall. Full artifacts land in results/:

results/
├── config.json      # exact run configuration (reproducible)
├── metrics.jsonl    # one line per request: timestamps, tokens, errors
├── system.jsonl     # GPU/CPU/RAM/network samples over time
├── summary.json     # aggregated metrics + derived estimates
├── timeline.json    # per-request phase spans (queue/waiting/decode)
├── findings.json    # automatic analysis results with evidence
├── report.html      # self-contained interactive report
└── charts/          # each chart as a standalone HTML file

No GPU? Try the mock server

python examples/mock_server.py --port 8399 --batch-size 8 &
inference-profiler profile --endpoint http://127.0.0.1:8399/v1 --model demo \
    --requests 100 --concurrency 4,8,16,32

The mock server queues requests beyond its batch size — the profiler will find the knee.

What it measures

Category Metrics
Latency TTFT, inter-token latency, end-to-end · P50/P90/P95/P99
Throughput requests/s, output tokens/s, total tokens/s
Tokens prompt/output totals, means, min/max, per-request decode speed
System GPU utilization & memory (NVML), CPU, RAM, network
Derived estimates batch utilization, prefill vs scheduler-wait split, GPU idle %, saturation knee

Measured numbers and heuristic estimates are kept strictly separate — estimates are suffixed *_estimate and their method is documented in docs/methodology.md. Findings are only ever generated from measured data.

Common recipes

# Concurrency sweep: find the throughput/latency knee
inference-profiler profile --endpoint http://localhost:8000/v1 --model llama3 \
    --requests 200 --concurrency 8,16,32,64,128

# Open-loop (Poisson arrivals at 25 req/s) — reveals queueing under overload
inference-profiler profile --endpoint http://localhost:8000/v1 --model llama3 \
    --requests 500 --arrival-mode open --rate 25

# Burst traffic
inference-profiler profile --endpoint http://localhost:8000/v1 --model llama3 \
    --requests 300 --arrival-mode burst --rate 50 --burst-size 40 --burst-idle 5

# Your own prompts (JSONL with a "prompt" field), controlled output lengths
inference-profiler profile --endpoint http://localhost:8000/v1 --model llama3 \
    --dataset examples/prompts.jsonl --output-tokens 64-256 --requests 200

# Everything in a config file (CLI flags override it)
inference-profiler profile --config examples/sweep_config.json

# Re-generate the report from raw data (tweak nothing, re-analyze)
inference-profiler report --results results/

Reading the report

  • Findings — ranked observations with the evidence that triggered them, e.g. “GPU utilization averaged only 42%” or “Throughput saturates near concurrency 16”.
  • Timeline — a waterfall of every request split into client-queue, waiting (TTFT), and decode phases. Growing gray/yellow bands = queueing; long blue = decode-bound.
  • Charts — latency/TTFT histograms, percentile curves, tokens/s over time, in-flight concurrency, GPU utilization & memory, prompt/output length vs latency, and concurrency scaling (on sweeps).

Architecture

cli ─▶ config (pydantic) ─▶ runner ──▶ workload   (synthetic / JSONL prompts)
                              │    ──▶ scheduler  (closed / open-poisson / burst)
                              │    ──▶ collector  (httpx + SSE timing per request)
                              │    ──▶ gpu_monitor (NVML/psutil background sampling)
                              ▼
                    metrics ─▶ timeline ─▶ analysis ─▶ charts ─▶ report.html

See docs/architecture.md. Adding a non-OpenAI backend means implementing one execute_request variant; everything downstream operates on RequestRecords and is backend-agnostic.

Development

git clone https://github.com/SarnadAbhilash/inference_profiler
cd inference-profiler
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest            # no GPU or server required — uses a mock transport
ruff check .
pre-commit install

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

inference_profiler-0.1.0.tar.gz (36.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

inference_profiler-0.1.0-py3-none-any.whl (34.0 kB view details)

Uploaded Python 3

File details

Details for the file inference_profiler-0.1.0.tar.gz.

File metadata

  • Download URL: inference_profiler-0.1.0.tar.gz
  • Upload date:
  • Size: 36.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for inference_profiler-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a957f7c16449f75328a72f9fa8ac268a1b5974345237f18f8f363f71950c243e
MD5 650ce322cc9139af609b22ab3393d03d
BLAKE2b-256 2c604f9800844ec519e31c4ca7b65cc8c04d2e310bc10f03154e3db26e82411a

See more details on using hashes here.

File details

Details for the file inference_profiler-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for inference_profiler-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b3e53b0c15e34133792693aee7ae9c94487248f7b83654ab5a662476dda0658b
MD5 760f393451d74c52f7ebfb33226a52fd
BLAKE2b-256 90d88bb5f50246c5f2d98a125a70293df250f87141126f9c9ddcda489dfa4789

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page