litellm/scripts
2026-08-29 17:31:11 -07:00
..
adaptive_router_demo feat: commit new adaptive routing 2026-04-18 21:29:39 -07:00
health_check feat(rate-limiter): allow opting out of v3 TPM reservation and Redis circuit breaker (#30211) 2026-06-11 10:34:26 -07:00
bench_sdk.py perf(build): strip native wheel symbols 2026-08-29 17:31:11 -07:00
bench_sdk_runtime.py wip 2026-08-28 10:01:07 -07:00
benchmark_anthropic_messages_perf.py perf: reduce per-request and per-chunk overhead across Anthropic streaming hot paths (#28289) 2026-05-23 12:15:59 -07:00
benchmark_chat_completions_perf.py perf: eliminate per-request callback scanning on proxy hot path (#27858) 2026-05-14 09:28:31 -07:00
benchmark_mock.py style: run black formatter on files from main merge 2026-04-17 13:02:59 -07:00
benchmark_model_response_creator.py fix: improve bedrock streaming hot path perf (#28720) 2026-05-28 11:31:37 -07:00
benchmark_proxy_vs_provider.py style: run black formatter on files from main merge 2026-04-17 13:02:59 -07:00
benchmark_streaming_chunk_overhead.py feat: litellm oss 110626 (#30202) 2026-06-11 22:30:26 -07:00
budget_ratchet_check.py feat(ci): ratchet the test suite's zero-assert, mock-echo and global-state debt (#37588) 2026-08-20 10:08:49 -07:00
check_test_quality.py feat(ci): gate patching of SDK internals in tests as TQ008 (#37787) 2026-08-22 22:54:30 -07:00
check_type_discipline.py perf(ci): fan the budget checkers out across cores (#37784) 2026-08-22 22:44:58 -07:00
create_litellm_branch.ps1 feat: add script to create branches with litellm_ prefix (#17606) 2025-12-06 10:41:39 -08:00
create_litellm_branch.sh enhance: create_litellm_branch tool to be more robust (#17874) 2025-12-12 05:35:50 -08:00
create_team_key_and_submit_guardrail.sh feat(guardrails): team-based guardrail registration and approval workflow (#22459) 2026-03-02 22:06:49 -08:00
eval_compression.py Prompt Compression - add it to the proxy (#25729) 2026-04-20 15:08:00 -07:00
gate_slot_lock.py refactor(make): stop queueing bootstrap for a machine-wide gate slot 2026-08-15 21:53:28 +00:00
install-cli.sh fix(install): pass an explicit Python version request to uv tool install 2026-07-26 21:02:35 -07:00
install.sh fix(install): pass an explicit Python version request to uv tool install 2026-07-26 21:02:35 -07:00
install_git_hooks.sh build(lint): rename make pre-commit to make check with a working-tree fallback 2026-08-08 03:25:35 -07:00
mock_bedrock_passthrough_target.py Refactor Bedrock response stream shape handling (#27257) 2026-05-06 17:39:38 -07:00
mock_grayswan_timeout_server.py implement failopen option default to True on grayswan guardrail (#18266) 2026-01-06 15:17:05 +05:30
mutation_report.py fix(ci): stop the mutation report publishing a score it never measured (#37825) 2026-08-21 20:15:52 -07:00
pre_commit_lint.sh feat(scripts): queue heavy gates behind a machine-wide slot lock 2026-08-14 17:22:32 -07:00
prisma_generate_if_needed.py fix(lint): generate the prisma client into the gate-owned venv 2026-08-06 01:54:26 -07:00
README.bench_sdk.md wip 2026-08-28 10:01:07 -07:00
ruff_strict_gate.py feat(scripts): queue heavy gates behind a machine-wide slot lock 2026-08-14 17:22:32 -07:00
test_agent_mcp_endpoints.sh Agents - assign tools (#22064) 2026-02-25 11:44:30 -08:00
test_bench_sdk.py perf(build): strip native wheel symbols 2026-08-29 17:31:11 -07:00
test_guardrails_register_endpoints.sh feat(guardrails): team-based guardrail registration and approval workflow (#22459) 2026-03-02 22:06:49 -08:00
test_quality_gate.py feat(ci): freeze the conftest save/restore inventory so it can only shrink (#37621) 2026-08-20 21:39:59 +00:00
test_tool_allowlist_script.py style: run black formatter on files from main merge 2026-04-17 13:02:59 -07:00
tpm_headline_test.sh fix: atomic TPM rate limit (#27001) 2026-05-05 16:58:07 -07:00
type_check_gate.py feat(scripts): queue heavy gates behind a machine-wide slot lock 2026-08-14 17:22:32 -07:00
type_discipline_gate.py feat(scripts): queue heavy gates behind a machine-wide slot lock 2026-08-14 17:22:32 -07:00
verify_adaptive_router.py feat: add adaptive routing to litellm 2026-04-18 16:35:17 -07:00
with_dashboard_node.sh fix(bootstrap): fail fast when nvm cannot activate the pinned node 2026-08-04 21:18:58 -07:00

SDK footprint and startup benchmark

Keep the harness in this repository, outside litellm/. One invocation measures one explicitly selected source and writes one artifact directory. It never checks out a revision or updates a shared results file, so the same harness can measure older revisions from separate checkouts

Run locally

Requires Linux or macOS, Python 3.10+, and uv. Select the same exact Python patch version on every comparison runner. The script declares pinned controller dependencies using inline script metadata, without installing LiteLLM's development environment

uv run --no-project --python 3.11 scripts/bench_sdk.py --local . --output /tmp/sdk-current

Exactly one of --local, --package, and --wheel is required. --local without a path means the current working directory. --package accepts an exact published version, not a range or latest. Both package and wheel modes require a compatible binary wheel and never fall back to compiling an sdist

Local mode copies source into a private temporary directory before invoking pip wheel, with PEP 517 build isolation enabled. Git checkouts include tracked working changes and untracked files that are not ignored; deleted and ignored files, Git metadata, and old ignored build products are excluded. Internal symlinks stay inside the copy. Non-Git source directories exclude common environment and build directories. Normal build outputs land in the copied source, and Cargo uses a private target directory. This is workspace isolation, not a security sandbox for untrusted build code. Use wheel mode when measuring a release artifact with generated assets absent from the source snapshot

A checkout must have its normal wheel build prerequisites, including Rust when its build backend requires it. Building and resolving dependencies need network access, but neither operation is a latency metric

For a quick smoke check:

uv run --no-project --python 3.11 scripts/bench_sdk.py \
  --local . --output /tmp/sdk-smoke --samples 3 --install-samples 1

For a published package, another checkout, or a prebuilt wheel:

uv run --no-project --python 3.11 scripts/bench_sdk.py \
  --package 1.98.0 --output /tmp/sdk-published

uv run --no-project --python 3.11 scripts/bench_sdk.py \
  --local /tmp/older-checkout --output /tmp/sdk-older

uv run --no-project --python 3.11 scripts/bench_sdk.py \
  --wheel /tmp/litellm-version-platform.whl --extras proxy --output /tmp/sdk-proxy

Use the actual wheel filename in the last command. Extras change the installed dependency set; the workload still exercises SDK completion, not proxy server startup

Rust build contract

The current root pyproject.toml declares maturin==1.9.4 as the PEP 517 backend and points it at litellm-rust/crates/python-bridge/Cargo.toml, with module name litellm.rust_bridge._native. Local mode therefore compiles the extension as part of the wheel build before installing or timing anything. Older checkouts use their own declared backend. There is no separate hand-maintained cargo build command in this harness

Python build isolation installs the backend, not a pinned Rust compiler or system linker. Those are runner prerequisites. The current Docker builder installs Rust and then installs the package via uv sync. CircleCI's Linux setup pins Rust 1.97.1, while its Windows setup uses floating stable. The workspace declares rust-version = "1.88", but the bridge does not set rust-version.workspace = true. A consistent compiler pin across runners and inheritance of the intended minimum are remaining build reproducibility gaps, outside this benchmark change. Cargo inheritance rules

Result metadata identifies the source mode, whether a build occurred, and native files present in the selected wheel. Build output is retained in run.log. Cargo's compiler and registry caches may be shared, but compiled target output, source snapshots, Python environments, and measured runtime state are private to each invocation

What it measures

Result Meaning
sizes.root_wheel_bytes Compressed LiteLLM wheel
sizes.resolved_wheelhouse_bytes LiteLLM and every selected dependency wheel, deduplicated by SHA-256
sizes.installed_delta_bytes File bytes after minus before each pristine install, including bytecode and entry points; symlinks excluded
timings.offline_install Hash-verified installation and bytecode compilation from the wheelhouse; environment creation excluded
timings.import Timer immediately around import litellm in each fresh process
timings.configuration Public completion arguments and telemetry configuration after import
timings.first_request First synchronous, non-streaming completion through a real HTTP client
timings.second_request Second completion in the same process, with connection reuse available
timings.import_to_first_response Start of import through the first response
timings.launch_to_import Parent launch timestamp through the child's import-complete timestamp
timings.launch_to_first_response Parent launch timestamp through the child's first response, excluding interpreter shutdown
timings.python_startup_exit pyperf command running python -I -B -c pass
timings.import_process_exit pyperf command running the guarded import probe, including process startup and shutdown

Durations are seconds. Every timing has raw samples, count, median, mean, sample standard deviation, median absolute deviation, minimum, and maximum. A single sample has no standard deviation. No percentile or statistical significance claim is made from small sample counts

diagnostics.json records externally sampled RSS/USS and loaded modules at import, configuration, first response, and second response. These four snapshots come from a separate process with a controller handshake, not a timing run. Module lists are relative to the diagnostic baseline and cumulative. USS is null when unavailable. importtime.log is also a separate diagnostic run

Isolation and repeatability

The controller contains pip, pyperf, psutil, and Pydantic for input validation. Target virtual environments have only the resolved wheel installation, without pip or benchmark packages. Every runtime sample starts a new interpreter with -I, an empty working directory, and an allowlisted environment. The current checkout and user site-packages cannot supply the import

pip compiles bytecode during installation. Runtime probes use -B, which reads existing bytecode but does not write more. Warmups are discarded and the OS filesystem cache is not flushed. A private home directory starts empty for each invocation and is shared across its samples. This measures process-cold startup with warm filesystem caches, not first-ever token cache initialization or serverless platform startup

The fake provider runs in the controller process on a dynamically assigned loopback port. It returns one fixed response, checks the request, and verifies exactly two requests per workflow probe. The SDK receives dummy credentials, zero retries, a request timeout, and the bundled model cost map setting. A Python audit hook blocks non-loopback socket operations and external DNS lookups; any blocked access fails the benchmark. This is a guard against accidental Python networking, not a security sandbox for native code or untrusted revisions

Import timing preloads only sys and time, not JSON, HTTP clients, psutil, or pyperf. Process-to-stage times use the system-wide monotonic performance clock shared by processes on the supported platforms. The controller server, audit hook, and minimal probe scaffolding have overhead, so compare like-for-like runs

Dependencies and backfills

Each run saves the exact wheelhouse, SHA-256 hashes, a hashed requirements.lock, dependency-only constraints.txt, pip installation reports, and an installed inventory. Dependencies must have binary wheels for the running Python/platform. An unavailable wheel fails explicitly instead of silently compiling an sdist

By default each source resolves its own declared requirements against the current index. That captures dependency changes but does not reconstruct the index as it existed at an old commit. For an implementation comparison, pass the same dependency constraints to both revisions:

uv run --no-project --python 3.11 scripts/bench_sdk.py \
  --local /tmp/candidate --constraints /tmp/sdk-current/constraints.txt \
  --output /tmp/sdk-candidate-pinned

An incompatible constraint fails instead of being relaxed. To replay without dependency downloads, use the saved root wheel as --wheel and the saved wheelhouse as --wheelhouse. This freezes the artifact universe on that Python/platform. --package VERSION --wheelhouse PATH also resolves that exact version from the archive. --wheelhouse does not make a local source build offline: the build backend and Rust dependencies can still need downloads. The controller tools must already be available locally

Run multiple invocations against separate checkouts and separate output directories for backfills. Every invocation has private venvs, build output, pip cache, home, and an ephemeral provider port. Existing output paths are refused. Use separate runners for timing comparisons; simultaneous CPU or disk work on one host contaminates the numbers. Revision selection, job matrices, aggregation, and publishing belong in the future GitHub Actions layer

Output and validation

Standard output contains only the complete JSON result; progress goes to stderr. result.json is written atomically only after every measurement succeeds. Failures exit nonzero and retain logs and artifacts, without a success result. Temporary target environments are always removed

The result records Python/platform, target and harness Git revisions and dirty flags, harness file hashes, tool versions, runtime environment settings, wheel metadata, and raw workflow samples. Archive the entire output directory, not just result.json

The pyperf files can be inspected with pyperf check, pyperf stats, and pyperf compare_to. Treat local smoke results as verification that the harness works, not evidence of a regression. Use repeated runs on the same idle runner before setting any thresholds

Run the focused tests in a controller environment with the same pinned packages:

uv run --no-project --with pip==26.2.1 --with pyperf==2.10.0 --with psutil==7.2.2 --with pydantic==2.13.4 \
  python -m unittest discover -s scripts -p test_bench_sdk.py -v

The tests use a small synthetic package to verify the harness without downloading LiteLLM dependencies. Real measurements always use the supplied LiteLLM wheel

This initial suite does not measure streaming/async paths, proxy boot, every provider, native allocation profiles, online installation latency, or cloud platform startup

Method references: pip repeatable installs, pip managing a separate interpreter, pyperf command