lmcache-cli 0.4.5.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lmcache/__init__.py +84 -0
- lmcache/_version.py +24 -0
- lmcache/cli/__init__.py +1 -0
- lmcache/cli/commands/__init__.py +34 -0
- lmcache/cli/commands/base.py +157 -0
- lmcache/cli/commands/bench/__init__.py +557 -0
- lmcache/cli/commands/bench/engine_bench/__init__.py +1 -0
- lmcache/cli/commands/bench/engine_bench/config.py +245 -0
- lmcache/cli/commands/bench/engine_bench/interactive/__init__.py +274 -0
- lmcache/cli/commands/bench/engine_bench/interactive/config.json +10 -0
- lmcache/cli/commands/bench/engine_bench/interactive/schema.py +352 -0
- lmcache/cli/commands/bench/engine_bench/interactive/state.py +327 -0
- lmcache/cli/commands/bench/engine_bench/interactive/terminal.py +291 -0
- lmcache/cli/commands/bench/engine_bench/progress.py +145 -0
- lmcache/cli/commands/bench/engine_bench/request_sender.py +232 -0
- lmcache/cli/commands/bench/engine_bench/stats.py +275 -0
- lmcache/cli/commands/bench/engine_bench/workloads/__init__.py +153 -0
- lmcache/cli/commands/bench/engine_bench/workloads/base.py +122 -0
- lmcache/cli/commands/bench/engine_bench/workloads/long_doc_permutator.py +435 -0
- lmcache/cli/commands/bench/engine_bench/workloads/long_doc_qa.py +281 -0
- lmcache/cli/commands/bench/engine_bench/workloads/multi_round_chat.py +337 -0
- lmcache/cli/commands/bench/engine_bench/workloads/random_prefill.py +178 -0
- lmcache/cli/commands/describe.py +310 -0
- lmcache/cli/commands/kvcache.py +133 -0
- lmcache/cli/commands/mock.py +75 -0
- lmcache/cli/commands/ping.py +113 -0
- lmcache/cli/commands/query/__init__.py +155 -0
- lmcache/cli/commands/query/prompt.py +134 -0
- lmcache/cli/commands/query/request.py +357 -0
- lmcache/cli/commands/server.py +99 -0
- lmcache/cli/commands/tool/__init__.py +63 -0
- lmcache/cli/commands/tool/cache_simulator.py +113 -0
- lmcache/cli/commands/trace/__init__.py +505 -0
- lmcache/cli/commands/trace/dispatch.py +249 -0
- lmcache/cli/commands/trace/driver.py +372 -0
- lmcache/cli/commands/trace/stats.py +289 -0
- lmcache/cli/documents/lmcache.txt +11 -0
- lmcache/cli/main.py +42 -0
- lmcache/cli/metrics/__init__.py +29 -0
- lmcache/cli/metrics/formatter.py +171 -0
- lmcache/cli/metrics/handler.py +94 -0
- lmcache/cli/metrics/metrics.py +161 -0
- lmcache/cli/metrics/section.py +77 -0
- lmcache/connections.py +173 -0
- lmcache/integration/__init__.py +2 -0
- lmcache/integration/base_service_factory.py +165 -0
- lmcache/integration/request_telemetry/__init__.py +1 -0
- lmcache/integration/request_telemetry/base.py +51 -0
- lmcache/integration/request_telemetry/factory.py +113 -0
- lmcache/integration/request_telemetry/fastapi.py +109 -0
- lmcache/integration/request_telemetry/noop.py +35 -0
- lmcache/integration/sglang/__init__.py +2 -0
- lmcache/integration/sglang/sglang_adapter.py +326 -0
- lmcache/integration/sglang/utils.py +39 -0
- lmcache/integration/vllm/__init__.py +1 -0
- lmcache/integration/vllm/lmcache_connector_v1.py +213 -0
- lmcache/integration/vllm/lmcache_connector_v1_085.py +150 -0
- lmcache/integration/vllm/lmcache_mp_connector_0180.py +1072 -0
- lmcache/integration/vllm/tests/test_mm_hash_utils.py +112 -0
- lmcache/integration/vllm/utils.py +433 -0
- lmcache/integration/vllm/vllm_multi_process_adapter.py +1090 -0
- lmcache/integration/vllm/vllm_service_factory.py +339 -0
- lmcache/integration/vllm/vllm_v1_adapter.py +1713 -0
- lmcache/logging.py +107 -0
- lmcache/native_storage_ops.pyi +230 -0
- lmcache/non_cuda_equivalents.py +1424 -0
- lmcache/observability.py +1958 -0
- lmcache/storage_backend/serde/__init__.py +1 -0
- lmcache/storage_backend/serde/cachegen_basics.py +210 -0
- lmcache/storage_backend/serde/cachegen_decoder.py +207 -0
- lmcache/storage_backend/serde/cachegen_encoder.py +394 -0
- lmcache/storage_backend/serde/serde.py +75 -0
- lmcache/tools/__init__.py +1 -0
- lmcache/tools/cache_simulator/README.md +392 -0
- lmcache/tools/cache_simulator/__init__.py +1 -0
- lmcache/tools/cache_simulator/docs/simulate_example.png +0 -0
- lmcache/tools/cache_simulator/docs/sweep_example.png +0 -0
- lmcache/tools/cache_simulator/gen_bench_dataset.py +360 -0
- lmcache/tools/cache_simulator/lru_cache.py +124 -0
- lmcache/tools/cache_simulator/plot_hit_rate.py +231 -0
- lmcache/tools/cache_simulator/simulator.py +795 -0
- lmcache/tools/controller_benchmark/README.md +161 -0
- lmcache/tools/controller_benchmark/__init__.py +1 -0
- lmcache/tools/controller_benchmark/__main__.py +331 -0
- lmcache/tools/controller_benchmark/benchmark.py +660 -0
- lmcache/tools/controller_benchmark/config.py +44 -0
- lmcache/tools/controller_benchmark/constants.py +10 -0
- lmcache/tools/controller_benchmark/handlers/__init__.py +46 -0
- lmcache/tools/controller_benchmark/handlers/admit.py +52 -0
- lmcache/tools/controller_benchmark/handlers/base.py +47 -0
- lmcache/tools/controller_benchmark/handlers/deregister.py +49 -0
- lmcache/tools/controller_benchmark/handlers/evict.py +52 -0
- lmcache/tools/controller_benchmark/handlers/heartbeat.py +56 -0
- lmcache/tools/controller_benchmark/handlers/p2p_lookup.py +47 -0
- lmcache/tools/controller_benchmark/handlers/register.py +56 -0
- lmcache/tools/mp_status_viewer/__init__.py +1 -0
- lmcache/tools/mp_status_viewer/__main__.py +95 -0
- lmcache/usage_context.py +417 -0
- lmcache/utils.py +665 -0
- lmcache/v1/__init__.py +2 -0
- lmcache/v1/api_server/__init__.py +2 -0
- lmcache/v1/api_server/__main__.py +537 -0
- lmcache/v1/basic_check.py +112 -0
- lmcache/v1/cache_controller/__init__.py +9 -0
- lmcache/v1/cache_controller/commands/__init__.py +15 -0
- lmcache/v1/cache_controller/commands/base.py +35 -0
- lmcache/v1/cache_controller/commands/full_sync.py +49 -0
- lmcache/v1/cache_controller/config.py +176 -0
- lmcache/v1/cache_controller/controller_manager.py +535 -0
- lmcache/v1/cache_controller/controllers/__init__.py +11 -0
- lmcache/v1/cache_controller/controllers/full_sync_tracker.py +473 -0
- lmcache/v1/cache_controller/controllers/kv_controller.py +439 -0
- lmcache/v1/cache_controller/controllers/registration_controller.py +282 -0
- lmcache/v1/cache_controller/executor.py +463 -0
- lmcache/v1/cache_controller/frontend/static/css/style.css +201 -0
- lmcache/v1/cache_controller/frontend/static/img/logo.png +0 -0
- lmcache/v1/cache_controller/frontend/static/index.html +234 -0
- lmcache/v1/cache_controller/frontend/static/js/controller_app.js +660 -0
- lmcache/v1/cache_controller/full_sync_sender.py +475 -0
- lmcache/v1/cache_controller/locks.py +149 -0
- lmcache/v1/cache_controller/message.py +828 -0
- lmcache/v1/cache_controller/observability.py +208 -0
- lmcache/v1/cache_controller/utils.py +679 -0
- lmcache/v1/cache_controller/worker.py +665 -0
- lmcache/v1/cache_engine.py +2058 -0
- lmcache/v1/cache_interface.py +19 -0
- lmcache/v1/check/__init__.py +74 -0
- lmcache/v1/check/check_mode_gen.py +86 -0
- lmcache/v1/check/check_mode_test_l2_adapter.py +284 -0
- lmcache/v1/check/check_mode_test_remote.py +155 -0
- lmcache/v1/check/check_mode_test_storage_manager.py +142 -0
- lmcache/v1/check/utils.py +571 -0
- lmcache/v1/compute/__init__.py +2 -0
- lmcache/v1/compute/attention/__init__.py +0 -0
- lmcache/v1/compute/attention/abstract.py +39 -0
- lmcache/v1/compute/attention/flash_attn.py +129 -0
- lmcache/v1/compute/attention/flash_infer_sparse.py +284 -0
- lmcache/v1/compute/attention/metadata.py +85 -0
- lmcache/v1/compute/attention/utils.py +14 -0
- lmcache/v1/compute/blend/__init__.py +7 -0
- lmcache/v1/compute/blend/blender.py +168 -0
- lmcache/v1/compute/blend/metadata.py +34 -0
- lmcache/v1/compute/blend/utils.py +63 -0
- lmcache/v1/compute/models/__init__.py +0 -0
- lmcache/v1/compute/models/base.py +141 -0
- lmcache/v1/compute/models/llama.py +9 -0
- lmcache/v1/compute/models/qwen3.py +24 -0
- lmcache/v1/compute/models/utils.py +68 -0
- lmcache/v1/compute/positional_encoding.py +199 -0
- lmcache/v1/config.py +848 -0
- lmcache/v1/config_base.py +848 -0
- lmcache/v1/distributed/api.py +248 -0
- lmcache/v1/distributed/config.py +321 -0
- lmcache/v1/distributed/error.py +64 -0
- lmcache/v1/distributed/eviction.py +192 -0
- lmcache/v1/distributed/eviction_policy/__init__.py +21 -0
- lmcache/v1/distributed/eviction_policy/factory.py +27 -0
- lmcache/v1/distributed/eviction_policy/lru.py +244 -0
- lmcache/v1/distributed/eviction_policy/noop.py +50 -0
- lmcache/v1/distributed/internal_api.py +170 -0
- lmcache/v1/distributed/l1_manager.py +835 -0
- lmcache/v1/distributed/l2_adapters/__init__.py +67 -0
- lmcache/v1/distributed/l2_adapters/base.py +360 -0
- lmcache/v1/distributed/l2_adapters/config.py +385 -0
- lmcache/v1/distributed/l2_adapters/factory.py +205 -0
- lmcache/v1/distributed/l2_adapters/fs_l2_adapter.py +747 -0
- lmcache/v1/distributed/l2_adapters/fs_native_l2_adapter.py +167 -0
- lmcache/v1/distributed/l2_adapters/mock_l2_adapter.py +516 -0
- lmcache/v1/distributed/l2_adapters/mooncake_store_l2_adapter.py +135 -0
- lmcache/v1/distributed/l2_adapters/native_connector_l2_adapter.py +468 -0
- lmcache/v1/distributed/l2_adapters/native_plugin_l2_adapter.py +199 -0
- lmcache/v1/distributed/l2_adapters/nixl_store_dynamic_l2_adapter.py +831 -0
- lmcache/v1/distributed/l2_adapters/nixl_store_l2_adapter.py +983 -0
- lmcache/v1/distributed/l2_adapters/plugin_l2_adapter.py +210 -0
- lmcache/v1/distributed/l2_adapters/resp_l2_adapter.py +176 -0
- lmcache/v1/distributed/memory_manager.py +179 -0
- lmcache/v1/distributed/storage_controller.py +39 -0
- lmcache/v1/distributed/storage_controllers/__init__.py +43 -0
- lmcache/v1/distributed/storage_controllers/eviction_controller.py +242 -0
- lmcache/v1/distributed/storage_controllers/prefetch_controller.py +830 -0
- lmcache/v1/distributed/storage_controllers/prefetch_policy.py +193 -0
- lmcache/v1/distributed/storage_controllers/store_controller.py +452 -0
- lmcache/v1/distributed/storage_controllers/store_policy.py +213 -0
- lmcache/v1/distributed/storage_manager.py +532 -0
- lmcache/v1/event_manager.py +145 -0
- lmcache/v1/exceptions/__init__.py +16 -0
- lmcache/v1/gpu_connector/__init__.py +126 -0
- lmcache/v1/gpu_connector/gpu_connectors.py +1906 -0
- lmcache/v1/gpu_connector/gpu_ops.py +85 -0
- lmcache/v1/gpu_connector/hpu_connector.py +326 -0
- lmcache/v1/gpu_connector/mock_gpu_connector.py +67 -0
- lmcache/v1/gpu_connector/utils.py +890 -0
- lmcache/v1/gpu_connector/xpu_connectors.py +916 -0
- lmcache/v1/health_monitor/__init__.py +1 -0
- lmcache/v1/health_monitor/base.py +587 -0
- lmcache/v1/health_monitor/checks/__init__.py +1 -0
- lmcache/v1/health_monitor/checks/remote_backend_check.py +304 -0
- lmcache/v1/health_monitor/constants.py +36 -0
- lmcache/v1/internal_api_server/__init__.py +0 -0
- lmcache/v1/internal_api_server/api_registry.py +59 -0
- lmcache/v1/internal_api_server/api_server.py +120 -0
- lmcache/v1/internal_api_server/common/__init__.py +1 -0
- lmcache/v1/internal_api_server/common/env_api.py +22 -0
- lmcache/v1/internal_api_server/common/loglevel_api.py +57 -0
- lmcache/v1/internal_api_server/common/metrics_api.py +29 -0
- lmcache/v1/internal_api_server/common/periodic_thread_api.py +138 -0
- lmcache/v1/internal_api_server/common/run_script_api.py +73 -0
- lmcache/v1/internal_api_server/common/thread_api.py +63 -0
- lmcache/v1/internal_api_server/controller/__init__.py +1 -0
- lmcache/v1/internal_api_server/controller/key_stats_api.py +81 -0
- lmcache/v1/internal_api_server/controller/worker_info_api.py +136 -0
- lmcache/v1/internal_api_server/utils.py +43 -0
- lmcache/v1/internal_api_server/vllm/__init__.py +1 -0
- lmcache/v1/internal_api_server/vllm/backend_api.py +221 -0
- lmcache/v1/internal_api_server/vllm/bypass_api.py +204 -0
- lmcache/v1/internal_api_server/vllm/cache_api.py +895 -0
- lmcache/v1/internal_api_server/vllm/chunk_statistics_api.py +141 -0
- lmcache/v1/internal_api_server/vllm/conf_api.py +147 -0
- lmcache/v1/internal_api_server/vllm/freeze_api.py +172 -0
- lmcache/v1/internal_api_server/vllm/hot_cache_api.py +184 -0
- lmcache/v1/internal_api_server/vllm/inference_api.py +65 -0
- lmcache/v1/internal_api_server/vllm/load_fs_chunks_api.py +320 -0
- lmcache/v1/internal_api_server/vllm/lookup_api.py +145 -0
- lmcache/v1/internal_api_server/vllm/version_api.py +25 -0
- lmcache/v1/kv_layer_groups.py +267 -0
- lmcache/v1/lazy_memory_allocator.py +284 -0
- lmcache/v1/lookup_client/__init__.py +25 -0
- lmcache/v1/lookup_client/abstract_client.py +77 -0
- lmcache/v1/lookup_client/async_lookup_message.py +50 -0
- lmcache/v1/lookup_client/chunk_statistics_lookup_client.py +200 -0
- lmcache/v1/lookup_client/factory.py +251 -0
- lmcache/v1/lookup_client/hit_limit_lookup_client.py +86 -0
- lmcache/v1/lookup_client/lmcache_async_lookup_client.py +407 -0
- lmcache/v1/lookup_client/lmcache_lookup_client.py +285 -0
- lmcache/v1/lookup_client/lmcache_lookup_client_bypass.py +99 -0
- lmcache/v1/lookup_client/mooncake_lookup_client.py +87 -0
- lmcache/v1/lookup_client/record_strategies/__init__.py +77 -0
- lmcache/v1/lookup_client/record_strategies/base.py +327 -0
- lmcache/v1/lookup_client/record_strategies/file_hash.py +130 -0
- lmcache/v1/lookup_client/record_strategies/memory_bloom_filter.py +81 -0
- lmcache/v1/manager.py +539 -0
- lmcache/v1/memory_management.py +2619 -0
- lmcache/v1/metadata.py +114 -0
- lmcache/v1/mp_observability/AGENTS.override.md +21 -0
- lmcache/v1/mp_observability/README.md +204 -0
- lmcache/v1/mp_observability/config.py +340 -0
- lmcache/v1/mp_observability/event.py +100 -0
- lmcache/v1/mp_observability/event_bus.py +313 -0
- lmcache/v1/mp_observability/otel_init.py +145 -0
- lmcache/v1/mp_observability/subscribers/__init__.py +28 -0
- lmcache/v1/mp_observability/subscribers/logging/__init__.py +19 -0
- lmcache/v1/mp_observability/subscribers/logging/l1.py +56 -0
- lmcache/v1/mp_observability/subscribers/logging/l2.py +73 -0
- lmcache/v1/mp_observability/subscribers/logging/lookup_hash.py +209 -0
- lmcache/v1/mp_observability/subscribers/logging/mp_server.py +90 -0
- lmcache/v1/mp_observability/subscribers/logging/sm.py +59 -0
- lmcache/v1/mp_observability/subscribers/metrics/__init__.py +20 -0
- lmcache/v1/mp_observability/subscribers/metrics/l0_lifecycle.py +290 -0
- lmcache/v1/mp_observability/subscribers/metrics/l1.py +55 -0
- lmcache/v1/mp_observability/subscribers/metrics/l1_lifecycle.py +166 -0
- lmcache/v1/mp_observability/subscribers/metrics/l2.py +121 -0
- lmcache/v1/mp_observability/subscribers/metrics/sm.py +69 -0
- lmcache/v1/mp_observability/subscribers/tracing/__init__.py +12 -0
- lmcache/v1/mp_observability/subscribers/tracing/mp_server.py +333 -0
- lmcache/v1/mp_observability/subscribers/tracing/span_registry.py +148 -0
- lmcache/v1/mp_observability/trace/__init__.py +50 -0
- lmcache/v1/mp_observability/trace/codecs.py +255 -0
- lmcache/v1/mp_observability/trace/decorator.py +147 -0
- lmcache/v1/mp_observability/trace/format.py +132 -0
- lmcache/v1/mp_observability/trace/lifecycle.py +83 -0
- lmcache/v1/mp_observability/trace/reader.py +167 -0
- lmcache/v1/mp_observability/trace/recorder.py +300 -0
- lmcache/v1/multiprocess/__init__.py +0 -0
- lmcache/v1/multiprocess/affinity_pool.py +102 -0
- lmcache/v1/multiprocess/blend_server_v2.py +891 -0
- lmcache/v1/multiprocess/config.py +253 -0
- lmcache/v1/multiprocess/custom_types.py +281 -0
- lmcache/v1/multiprocess/futures.py +194 -0
- lmcache/v1/multiprocess/gpu_context.py +511 -0
- lmcache/v1/multiprocess/http_server.py +235 -0
- lmcache/v1/multiprocess/mp_runtime_plugin_launcher.py +130 -0
- lmcache/v1/multiprocess/mq.py +732 -0
- lmcache/v1/multiprocess/protocol.py +86 -0
- lmcache/v1/multiprocess/protocols/README.md +213 -0
- lmcache/v1/multiprocess/protocols/__init__.py +127 -0
- lmcache/v1/multiprocess/protocols/base.py +89 -0
- lmcache/v1/multiprocess/protocols/blend.py +109 -0
- lmcache/v1/multiprocess/protocols/blend_v2.py +57 -0
- lmcache/v1/multiprocess/protocols/controller.py +53 -0
- lmcache/v1/multiprocess/protocols/debug.py +34 -0
- lmcache/v1/multiprocess/protocols/engine.py +146 -0
- lmcache/v1/multiprocess/protocols/observability.py +39 -0
- lmcache/v1/multiprocess/server.py +1134 -0
- lmcache/v1/multiprocess/session.py +190 -0
- lmcache/v1/multiprocess/token_hasher.py +441 -0
- lmcache/v1/offload_server/__init__.py +17 -0
- lmcache/v1/offload_server/abstract_server.py +37 -0
- lmcache/v1/offload_server/message.py +30 -0
- lmcache/v1/offload_server/zmq_server.py +122 -0
- lmcache/v1/periodic_thread.py +579 -0
- lmcache/v1/pin_monitor.py +246 -0
- lmcache/v1/plugin/__init__.py +0 -0
- lmcache/v1/plugin/runtime_plugin_launcher.py +211 -0
- lmcache/v1/protocol.py +317 -0
- lmcache/v1/rpc/__init__.py +17 -0
- lmcache/v1/rpc/transport.py +105 -0
- lmcache/v1/rpc/zmq_transport.py +213 -0
- lmcache/v1/rpc_utils.py +165 -0
- lmcache/v1/server/__init__.py +2 -0
- lmcache/v1/server/__main__.py +170 -0
- lmcache/v1/server/storage_backend/__init__.py +21 -0
- lmcache/v1/server/storage_backend/abstract_backend.py +80 -0
- lmcache/v1/server/storage_backend/local_backend.py +75 -0
- lmcache/v1/server/utils.py +21 -0
- lmcache/v1/standalone/__init__.py +1 -0
- lmcache/v1/standalone/__main__.py +583 -0
- lmcache/v1/standalone/manager.py +80 -0
- lmcache/v1/standalone/standalone_service_factory.py +86 -0
- lmcache/v1/storage_backend/__init__.py +313 -0
- lmcache/v1/storage_backend/abstract_backend.py +445 -0
- lmcache/v1/storage_backend/audit_backend.py +233 -0
- lmcache/v1/storage_backend/batched_message_sender.py +222 -0
- lmcache/v1/storage_backend/cache_policy/__init__.py +45 -0
- lmcache/v1/storage_backend/cache_policy/base_policy.py +87 -0
- lmcache/v1/storage_backend/cache_policy/fifo.py +58 -0
- lmcache/v1/storage_backend/cache_policy/lfu.py +105 -0
- lmcache/v1/storage_backend/cache_policy/lru.py +81 -0
- lmcache/v1/storage_backend/cache_policy/mru.py +61 -0
- lmcache/v1/storage_backend/connector/__init__.py +443 -0
- lmcache/v1/storage_backend/connector/audit_adapter.py +77 -0
- lmcache/v1/storage_backend/connector/audit_connector.py +320 -0
- lmcache/v1/storage_backend/connector/base_connector.py +379 -0
- lmcache/v1/storage_backend/connector/blackhole_adapter.py +21 -0
- lmcache/v1/storage_backend/connector/blackhole_connector.py +37 -0
- lmcache/v1/storage_backend/connector/eic_adapter.py +31 -0
- lmcache/v1/storage_backend/connector/eic_connector.py +757 -0
- lmcache/v1/storage_backend/connector/external_adapter.py +79 -0
- lmcache/v1/storage_backend/connector/fs_adapter.py +51 -0
- lmcache/v1/storage_backend/connector/fs_connector.py +403 -0
- lmcache/v1/storage_backend/connector/infinistore_adapter.py +56 -0
- lmcache/v1/storage_backend/connector/infinistore_connector.py +177 -0
- lmcache/v1/storage_backend/connector/instrumented_connector.py +219 -0
- lmcache/v1/storage_backend/connector/lm_adapter.py +31 -0
- lmcache/v1/storage_backend/connector/lm_connector.py +176 -0
- lmcache/v1/storage_backend/connector/mock_adapter.py +57 -0
- lmcache/v1/storage_backend/connector/mock_connector.py +349 -0
- lmcache/v1/storage_backend/connector/mooncakestore_adapter.py +43 -0
- lmcache/v1/storage_backend/connector/mooncakestore_connector.py +614 -0
- lmcache/v1/storage_backend/connector/redis_adapter.py +181 -0
- lmcache/v1/storage_backend/connector/redis_connector.py +828 -0
- lmcache/v1/storage_backend/connector/s3_adapter.py +59 -0
- lmcache/v1/storage_backend/connector/s3_connector.py +699 -0
- lmcache/v1/storage_backend/connector/sagemaker_hyperpod_adapter.py +233 -0
- lmcache/v1/storage_backend/connector/sagemaker_hyperpod_connector.py +987 -0
- lmcache/v1/storage_backend/connector/valkey_adapter.py +114 -0
- lmcache/v1/storage_backend/connector/valkey_connector.py +627 -0
- lmcache/v1/storage_backend/gds_backend.py +1199 -0
- lmcache/v1/storage_backend/job_executor/__init__.py +0 -0
- lmcache/v1/storage_backend/job_executor/base_executor.py +34 -0
- lmcache/v1/storage_backend/job_executor/pq_executor.py +235 -0
- lmcache/v1/storage_backend/local_cpu_backend.py +810 -0
- lmcache/v1/storage_backend/local_disk_backend.py +656 -0
- lmcache/v1/storage_backend/maru_backend.py +734 -0
- lmcache/v1/storage_backend/naive_serde/__init__.py +50 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_basics.py +133 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_decoder.py +135 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_encoder.py +83 -0
- lmcache/v1/storage_backend/naive_serde/kivi_serde.py +22 -0
- lmcache/v1/storage_backend/naive_serde/naive_serde.py +18 -0
- lmcache/v1/storage_backend/naive_serde/serde.py +37 -0
- lmcache/v1/storage_backend/native_clients/connector_client_base.py +165 -0
- lmcache/v1/storage_backend/native_clients/resp_client.py +35 -0
- lmcache/v1/storage_backend/nixl_storage_backend.py +1400 -0
- lmcache/v1/storage_backend/p2p_backend.py +788 -0
- lmcache/v1/storage_backend/path_sharder.py +117 -0
- lmcache/v1/storage_backend/pd_backend.py +646 -0
- lmcache/v1/storage_backend/plugins/dax_backend.py +1443 -0
- lmcache/v1/storage_backend/plugins/rust_raw_block_backend.py +1361 -0
- lmcache/v1/storage_backend/remote_backend.py +624 -0
- lmcache/v1/storage_backend/resp_client.py +227 -0
- lmcache/v1/storage_backend/storage_backend_listener.py +19 -0
- lmcache/v1/storage_backend/storage_manager.py +1352 -0
- lmcache/v1/system_detection.py +110 -0
- lmcache/v1/token_database.py +551 -0
- lmcache/v1/transfer_channel/__init__.py +83 -0
- lmcache/v1/transfer_channel/abstract.py +285 -0
- lmcache/v1/transfer_channel/mock_memory_channel.py +156 -0
- lmcache/v1/transfer_channel/nixl_channel.py +639 -0
- lmcache/v1/transfer_channel/py_socket_channel.py +260 -0
- lmcache/v1/transfer_channel/transfer_utils.py +63 -0
- lmcache/v1/utils/__init__.py +1 -0
- lmcache/v1/utils/bloom_filter.py +109 -0
- lmcache/v1/utils/cache_utils.py +125 -0
- lmcache_cli-0.4.5.dev0.dist-info/METADATA +185 -0
- lmcache_cli-0.4.5.dev0.dist-info/RECORD +399 -0
- lmcache_cli-0.4.5.dev0.dist-info/WHEEL +5 -0
- lmcache_cli-0.4.5.dev0.dist-info/entry_points.txt +2 -0
- lmcache_cli-0.4.5.dev0.dist-info/licenses/LICENSE +201 -0
- lmcache_cli-0.4.5.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""``lmcache bench`` command — sustained performance benchmarking."""
|
|
3
|
+
|
|
4
|
+
# Standard
|
|
5
|
+
import argparse
|
|
6
|
+
import asyncio
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
# First Party
|
|
11
|
+
from lmcache.cli.commands.base import BaseCommand
|
|
12
|
+
from lmcache.cli.commands.bench.engine_bench.config import (
|
|
13
|
+
EngineBenchConfig,
|
|
14
|
+
parse_args_to_config,
|
|
15
|
+
)
|
|
16
|
+
from lmcache.cli.commands.bench.engine_bench.interactive import run_interactive
|
|
17
|
+
from lmcache.cli.commands.bench.engine_bench.interactive.state import (
|
|
18
|
+
InteractiveState,
|
|
19
|
+
)
|
|
20
|
+
from lmcache.cli.commands.bench.engine_bench.progress import ProgressMonitor
|
|
21
|
+
from lmcache.cli.commands.bench.engine_bench.request_sender import (
|
|
22
|
+
RequestSender,
|
|
23
|
+
)
|
|
24
|
+
from lmcache.cli.commands.bench.engine_bench.stats import (
|
|
25
|
+
FinalStats,
|
|
26
|
+
StatsCollector,
|
|
27
|
+
)
|
|
28
|
+
from lmcache.cli.commands.bench.engine_bench.workloads import create_workload
|
|
29
|
+
from lmcache.logging import init_logger
|
|
30
|
+
|
|
31
|
+
logger = init_logger(__name__)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class BenchCommand(BaseCommand):
|
|
35
|
+
"""CLI command for sustained performance benchmarking."""
|
|
36
|
+
|
|
37
|
+
def name(self) -> str:
|
|
38
|
+
return "bench"
|
|
39
|
+
|
|
40
|
+
def help(self) -> str:
|
|
41
|
+
return "Run sustained performance benchmarks."
|
|
42
|
+
|
|
43
|
+
def add_arguments(self, _parser: argparse.ArgumentParser) -> None:
|
|
44
|
+
pass # args registered in register() via subparsers
|
|
45
|
+
|
|
46
|
+
def register(self, subparsers: argparse._SubParsersAction) -> None:
|
|
47
|
+
parser = subparsers.add_parser(
|
|
48
|
+
self.name(),
|
|
49
|
+
help=self.help(),
|
|
50
|
+
description="Run sustained performance benchmarks.",
|
|
51
|
+
)
|
|
52
|
+
inner = parser.add_subparsers(
|
|
53
|
+
dest="bench_target",
|
|
54
|
+
required=True,
|
|
55
|
+
metavar="{engine}",
|
|
56
|
+
)
|
|
57
|
+
self._register_engine(inner)
|
|
58
|
+
|
|
59
|
+
def _register_engine(
|
|
60
|
+
self,
|
|
61
|
+
subparsers: argparse._SubParsersAction,
|
|
62
|
+
) -> None:
|
|
63
|
+
parser = subparsers.add_parser(
|
|
64
|
+
"engine",
|
|
65
|
+
help="Benchmark an inference engine.",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# --- Config file ---
|
|
69
|
+
parser.add_argument(
|
|
70
|
+
"--config",
|
|
71
|
+
default=None,
|
|
72
|
+
metavar="FILE",
|
|
73
|
+
help="Load configuration from a JSON file (skips interactive mode).",
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# --- General args ---
|
|
77
|
+
parser.add_argument(
|
|
78
|
+
"--engine-url",
|
|
79
|
+
default=None,
|
|
80
|
+
help=(
|
|
81
|
+
"Inference engine URL (e.g., http://localhost:8000). "
|
|
82
|
+
"Set OPENAI_API_KEY env var if authentication is needed."
|
|
83
|
+
),
|
|
84
|
+
)
|
|
85
|
+
parser.add_argument(
|
|
86
|
+
"--lmcache-url",
|
|
87
|
+
default=None,
|
|
88
|
+
help="LMCache MP server URL for auto-detecting tokens per GB.",
|
|
89
|
+
)
|
|
90
|
+
parser.add_argument(
|
|
91
|
+
"--model",
|
|
92
|
+
default=None,
|
|
93
|
+
help="Model name (auto-detected from engine if omitted).",
|
|
94
|
+
)
|
|
95
|
+
parser.add_argument(
|
|
96
|
+
"--workload",
|
|
97
|
+
default=None,
|
|
98
|
+
choices=[
|
|
99
|
+
"long-doc-permutator",
|
|
100
|
+
"long-doc-qa",
|
|
101
|
+
"multi-round-chat",
|
|
102
|
+
"random-prefill",
|
|
103
|
+
],
|
|
104
|
+
help="Workload type.",
|
|
105
|
+
)
|
|
106
|
+
parser.add_argument(
|
|
107
|
+
"--kv-cache-volume",
|
|
108
|
+
type=float,
|
|
109
|
+
default=100.0,
|
|
110
|
+
help="Target active KV cache in GB (default: 100).",
|
|
111
|
+
)
|
|
112
|
+
parser.add_argument(
|
|
113
|
+
"--tokens-per-gb-kvcache",
|
|
114
|
+
type=int,
|
|
115
|
+
default=None,
|
|
116
|
+
help=("Tokens per GB of KV cache (required if --lmcache-url is not set)."),
|
|
117
|
+
)
|
|
118
|
+
parser.add_argument(
|
|
119
|
+
"--seed",
|
|
120
|
+
type=int,
|
|
121
|
+
default=42,
|
|
122
|
+
help="Random seed (default: 42).",
|
|
123
|
+
)
|
|
124
|
+
parser.add_argument(
|
|
125
|
+
"--output-dir",
|
|
126
|
+
default=".",
|
|
127
|
+
help="Directory for output files (default: current).",
|
|
128
|
+
)
|
|
129
|
+
parser.add_argument(
|
|
130
|
+
"--no-csv",
|
|
131
|
+
action="store_true",
|
|
132
|
+
help="Skip CSV export.",
|
|
133
|
+
)
|
|
134
|
+
parser.add_argument(
|
|
135
|
+
"--json",
|
|
136
|
+
action="store_true",
|
|
137
|
+
help="Export JSON summary.",
|
|
138
|
+
)
|
|
139
|
+
parser.add_argument(
|
|
140
|
+
"-q",
|
|
141
|
+
"--quiet",
|
|
142
|
+
action="store_true",
|
|
143
|
+
help="Suppress real-time progress display.",
|
|
144
|
+
)
|
|
145
|
+
parser.add_argument(
|
|
146
|
+
"--no-interactive",
|
|
147
|
+
action="store_true",
|
|
148
|
+
help=(
|
|
149
|
+
"Disable interactive mode. Errors if required arguments are missing."
|
|
150
|
+
),
|
|
151
|
+
)
|
|
152
|
+
parser.add_argument(
|
|
153
|
+
"--export-config",
|
|
154
|
+
default=None,
|
|
155
|
+
metavar="FILE",
|
|
156
|
+
help=(
|
|
157
|
+
"Export resolved configuration to a JSON file and exit. "
|
|
158
|
+
"Does not run the benchmark or enter interactive mode."
|
|
159
|
+
),
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# --- Long-doc-permutator workload args ---
|
|
163
|
+
ldp_group = parser.add_argument_group("long-doc-permutator workload options")
|
|
164
|
+
ldp_group.add_argument(
|
|
165
|
+
"--ldp-num-contexts",
|
|
166
|
+
type=int,
|
|
167
|
+
default=5,
|
|
168
|
+
help="Number of unique context documents (default: 5).",
|
|
169
|
+
)
|
|
170
|
+
ldp_group.add_argument(
|
|
171
|
+
"--ldp-context-length",
|
|
172
|
+
type=int,
|
|
173
|
+
default=5000,
|
|
174
|
+
help="Token length of each context (default: 5000).",
|
|
175
|
+
)
|
|
176
|
+
ldp_group.add_argument(
|
|
177
|
+
"--ldp-system-prompt-length",
|
|
178
|
+
type=int,
|
|
179
|
+
default=1000,
|
|
180
|
+
help="Token length of the shared system prompt (default: 1000). "
|
|
181
|
+
"Use 0 for no system prompt.",
|
|
182
|
+
)
|
|
183
|
+
ldp_group.add_argument(
|
|
184
|
+
"--ldp-num-permutations",
|
|
185
|
+
type=int,
|
|
186
|
+
default=10,
|
|
187
|
+
help="Number of distinct permutations to send (default: 10). "
|
|
188
|
+
"Capped at N! where N = --ldp-num-contexts.",
|
|
189
|
+
)
|
|
190
|
+
ldp_group.add_argument(
|
|
191
|
+
"--ldp-num-inflight-requests",
|
|
192
|
+
type=int,
|
|
193
|
+
default=1,
|
|
194
|
+
help="Max concurrent in-flight requests (default: 1).",
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# --- Long-doc-qa workload args ---
|
|
198
|
+
group = parser.add_argument_group("long-doc-qa workload options")
|
|
199
|
+
group.add_argument(
|
|
200
|
+
"--ldqa-document-length",
|
|
201
|
+
type=int,
|
|
202
|
+
default=10000,
|
|
203
|
+
help="Token length per document (default: 10000).",
|
|
204
|
+
)
|
|
205
|
+
group.add_argument(
|
|
206
|
+
"--ldqa-query-per-document",
|
|
207
|
+
type=int,
|
|
208
|
+
default=2,
|
|
209
|
+
help="Questions per document (default: 2).",
|
|
210
|
+
)
|
|
211
|
+
group.add_argument(
|
|
212
|
+
"--ldqa-shuffle-policy",
|
|
213
|
+
default="random",
|
|
214
|
+
choices=["random", "tile"],
|
|
215
|
+
help="Request ordering (default: random).",
|
|
216
|
+
)
|
|
217
|
+
group.add_argument(
|
|
218
|
+
"--ldqa-num-inflight-requests",
|
|
219
|
+
type=int,
|
|
220
|
+
default=3,
|
|
221
|
+
help="Max concurrent in-flight requests (default: 3).",
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
# --- Multi-round-chat workload args ---
|
|
225
|
+
mrc_group = parser.add_argument_group(
|
|
226
|
+
"multi-round-chat workload options",
|
|
227
|
+
)
|
|
228
|
+
mrc_group.add_argument(
|
|
229
|
+
"--mrc-shared-prompt-length",
|
|
230
|
+
type=int,
|
|
231
|
+
default=2000,
|
|
232
|
+
help="System prompt token length (default: 2000).",
|
|
233
|
+
)
|
|
234
|
+
mrc_group.add_argument(
|
|
235
|
+
"--mrc-chat-history-length",
|
|
236
|
+
type=int,
|
|
237
|
+
default=10000,
|
|
238
|
+
help="Pre-filled chat history token length (default: 10000).",
|
|
239
|
+
)
|
|
240
|
+
mrc_group.add_argument(
|
|
241
|
+
"--mrc-user-input-length",
|
|
242
|
+
type=int,
|
|
243
|
+
default=50,
|
|
244
|
+
help="Tokens per user query (default: 50).",
|
|
245
|
+
)
|
|
246
|
+
mrc_group.add_argument(
|
|
247
|
+
"--mrc-output-length",
|
|
248
|
+
type=int,
|
|
249
|
+
default=200,
|
|
250
|
+
help="Max tokens to generate per response (default: 200).",
|
|
251
|
+
)
|
|
252
|
+
mrc_group.add_argument(
|
|
253
|
+
"--mrc-qps",
|
|
254
|
+
type=float,
|
|
255
|
+
default=1.0,
|
|
256
|
+
help="Queries per second (default: 1.0).",
|
|
257
|
+
)
|
|
258
|
+
mrc_group.add_argument(
|
|
259
|
+
"--mrc-duration",
|
|
260
|
+
type=float,
|
|
261
|
+
default=60.0,
|
|
262
|
+
help="Benchmark duration in seconds (default: 60).",
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# --- Random-prefill workload args ---
|
|
266
|
+
rp_group = parser.add_argument_group(
|
|
267
|
+
"random-prefill workload options",
|
|
268
|
+
)
|
|
269
|
+
rp_group.add_argument(
|
|
270
|
+
"--rp-request-length",
|
|
271
|
+
type=int,
|
|
272
|
+
default=10000,
|
|
273
|
+
help="Token length per request (default: 10000).",
|
|
274
|
+
)
|
|
275
|
+
rp_group.add_argument(
|
|
276
|
+
"--rp-num-requests",
|
|
277
|
+
type=int,
|
|
278
|
+
default=50,
|
|
279
|
+
help="Number of requests to send (default: 50).",
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
parser.set_defaults(func=self.execute)
|
|
283
|
+
|
|
284
|
+
def execute(self, args: argparse.Namespace) -> None:
|
|
285
|
+
handlers = {"engine": self._bench_engine}
|
|
286
|
+
handler = handlers.get(args.bench_target)
|
|
287
|
+
if handler is None:
|
|
288
|
+
print(
|
|
289
|
+
f"Unknown bench target: {args.bench_target}",
|
|
290
|
+
file=sys.stderr,
|
|
291
|
+
)
|
|
292
|
+
sys.exit(1)
|
|
293
|
+
handler(args)
|
|
294
|
+
|
|
295
|
+
# ------------------------------------------------------------------
|
|
296
|
+
# Engine benchmark orchestrator
|
|
297
|
+
# ------------------------------------------------------------------
|
|
298
|
+
|
|
299
|
+
def _get_missing_args(self, args: argparse.Namespace) -> list[str]:
|
|
300
|
+
"""Return list of missing required CLI flags."""
|
|
301
|
+
missing: list[str] = []
|
|
302
|
+
if args.engine_url is None:
|
|
303
|
+
missing.append("--engine-url")
|
|
304
|
+
if args.workload is None:
|
|
305
|
+
missing.append("--workload")
|
|
306
|
+
if (
|
|
307
|
+
args.tokens_per_gb_kvcache is None
|
|
308
|
+
and getattr(args, "lmcache_url", None) is None
|
|
309
|
+
):
|
|
310
|
+
missing.append("--tokens-per-gb-kvcache or --lmcache-url")
|
|
311
|
+
return missing
|
|
312
|
+
|
|
313
|
+
def _needs_interactive(self, args: argparse.Namespace) -> bool:
|
|
314
|
+
"""Check whether interactive mode should be triggered."""
|
|
315
|
+
if getattr(args, "config", None):
|
|
316
|
+
return False
|
|
317
|
+
return len(self._get_missing_args(args)) > 0
|
|
318
|
+
|
|
319
|
+
def _resolve_args(self, args: argparse.Namespace) -> argparse.Namespace:
|
|
320
|
+
"""Resolve args via config file, interactive mode, or pass through."""
|
|
321
|
+
# Case 1: --config file
|
|
322
|
+
config_path = getattr(args, "config", None)
|
|
323
|
+
if config_path:
|
|
324
|
+
state = InteractiveState.load_json(config_path)
|
|
325
|
+
state.merge_cli_args(args)
|
|
326
|
+
resolved = state.to_namespace()
|
|
327
|
+
# Carry over output flags from CLI
|
|
328
|
+
for attr in (
|
|
329
|
+
"output_dir",
|
|
330
|
+
"seed",
|
|
331
|
+
"no_csv",
|
|
332
|
+
"json",
|
|
333
|
+
"quiet",
|
|
334
|
+
"format",
|
|
335
|
+
"output",
|
|
336
|
+
):
|
|
337
|
+
cli_val = getattr(args, attr, None)
|
|
338
|
+
if cli_val is not None:
|
|
339
|
+
setattr(resolved, attr, cli_val)
|
|
340
|
+
return resolved
|
|
341
|
+
|
|
342
|
+
# Case 2: --no-interactive or --export-config — error if missing
|
|
343
|
+
no_interactive = getattr(args, "no_interactive", False)
|
|
344
|
+
export_config = getattr(args, "export_config", None)
|
|
345
|
+
if no_interactive or export_config:
|
|
346
|
+
missing = self._get_missing_args(args)
|
|
347
|
+
if missing:
|
|
348
|
+
flag = "--export-config" if export_config else "--no-interactive"
|
|
349
|
+
raise SystemExit(
|
|
350
|
+
"Missing required arguments: "
|
|
351
|
+
+ ", ".join(missing)
|
|
352
|
+
+ f". Provide them or remove {flag} "
|
|
353
|
+
"for guided setup."
|
|
354
|
+
)
|
|
355
|
+
return args
|
|
356
|
+
|
|
357
|
+
# Case 3: Interactive mode
|
|
358
|
+
if self._needs_interactive(args):
|
|
359
|
+
return run_interactive(args)
|
|
360
|
+
|
|
361
|
+
# Case 4: All required args present — run directly
|
|
362
|
+
return args
|
|
363
|
+
|
|
364
|
+
def _export_config(
|
|
365
|
+
self,
|
|
366
|
+
config: EngineBenchConfig,
|
|
367
|
+
args: argparse.Namespace,
|
|
368
|
+
path: str,
|
|
369
|
+
) -> None:
|
|
370
|
+
"""Export resolved config to JSON and exit.
|
|
371
|
+
|
|
372
|
+
Builds a standalone config dict from the resolved
|
|
373
|
+
``EngineBenchConfig`` and workload-specific CLI args.
|
|
374
|
+
Environment-specific keys (``engine_url``, ``lmcache_url``)
|
|
375
|
+
are excluded by ``InteractiveState.to_json()`` so the exported
|
|
376
|
+
config is portable.
|
|
377
|
+
"""
|
|
378
|
+
# Standard
|
|
379
|
+
import json as json_mod
|
|
380
|
+
|
|
381
|
+
state = InteractiveState()
|
|
382
|
+
state.set("engine_url", config.engine_url)
|
|
383
|
+
state.set("model", config.model)
|
|
384
|
+
state.set("workload", config.workload)
|
|
385
|
+
state.set("kv_cache_volume", config.kv_cache_volume_gb)
|
|
386
|
+
state.set("tokens_per_gb_kvcache", config.tokens_per_gb_kvcache)
|
|
387
|
+
|
|
388
|
+
# Workload-specific args from namespace
|
|
389
|
+
for item in state.get_workload_items():
|
|
390
|
+
value = getattr(args, item.key, item.default)
|
|
391
|
+
if value is not None:
|
|
392
|
+
state.set(item.key, value)
|
|
393
|
+
|
|
394
|
+
# to_json() handles filtering out engine_url, lmcache_url, etc.
|
|
395
|
+
data = state.to_json()
|
|
396
|
+
|
|
397
|
+
with open(path, "w") as f:
|
|
398
|
+
json_mod.dump(data, f, indent=2)
|
|
399
|
+
f.write("\n")
|
|
400
|
+
|
|
401
|
+
print(f"Configuration exported to {path}")
|
|
402
|
+
print(
|
|
403
|
+
f"\033[1mReplay with:\033[0m \033[96mlmcache bench engine "
|
|
404
|
+
f"--engine-url <URL> --config {path}\033[0m"
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
def _bench_engine(self, args: argparse.Namespace) -> None:
|
|
408
|
+
"""Centralized orchestrator: create all modules and run benchmark."""
|
|
409
|
+
# 0. Resolve args (config file / interactive / pass-through)
|
|
410
|
+
args = self._resolve_args(args)
|
|
411
|
+
|
|
412
|
+
# 1. Parse config
|
|
413
|
+
config = parse_args_to_config(args)
|
|
414
|
+
|
|
415
|
+
# 1b. --export-config: save resolved config and exit
|
|
416
|
+
export_path = getattr(args, "export_config", None)
|
|
417
|
+
if export_path:
|
|
418
|
+
self._export_config(config, args, export_path)
|
|
419
|
+
return
|
|
420
|
+
|
|
421
|
+
logger.info(
|
|
422
|
+
"Benchmark config: workload=%s, model=%s, "
|
|
423
|
+
"kv_cache=%.1f GB, tokens_per_gb=%d",
|
|
424
|
+
config.workload,
|
|
425
|
+
config.model,
|
|
426
|
+
config.kv_cache_volume_gb,
|
|
427
|
+
config.tokens_per_gb_kvcache,
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
# 2. Create shared modules
|
|
431
|
+
stats_collector = StatsCollector()
|
|
432
|
+
progress_monitor = ProgressMonitor(
|
|
433
|
+
stats_collector,
|
|
434
|
+
quiet=config.quiet,
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
# 3. Create request sender (callbacks wired after workload creation)
|
|
438
|
+
request_sender = RequestSender(config.engine_url, config.model)
|
|
439
|
+
|
|
440
|
+
# 4. Create workload
|
|
441
|
+
workload = create_workload(
|
|
442
|
+
config,
|
|
443
|
+
args,
|
|
444
|
+
request_sender,
|
|
445
|
+
stats_collector,
|
|
446
|
+
progress_monitor,
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
# 5. Wire callbacks on sender
|
|
450
|
+
request_sender.add_on_finished_callback(
|
|
451
|
+
lambda result, _text: stats_collector.on_request_finished(result),
|
|
452
|
+
)
|
|
453
|
+
request_sender.add_on_finished_callback(
|
|
454
|
+
lambda result, _text: progress_monitor.on_request_finished(
|
|
455
|
+
result.request_id,
|
|
456
|
+
result.successful,
|
|
457
|
+
),
|
|
458
|
+
)
|
|
459
|
+
request_sender.add_on_finished_callback(workload.request_finished)
|
|
460
|
+
|
|
461
|
+
# 6. Log config and run benchmark
|
|
462
|
+
workload.log_config()
|
|
463
|
+
progress_monitor.start()
|
|
464
|
+
try:
|
|
465
|
+
workload.run()
|
|
466
|
+
finally:
|
|
467
|
+
progress_monitor.stop()
|
|
468
|
+
asyncio.run(request_sender.close())
|
|
469
|
+
|
|
470
|
+
# 7. Final metrics
|
|
471
|
+
final = stats_collector.get_final_stats()
|
|
472
|
+
self._emit_final_metrics(config, final, args)
|
|
473
|
+
|
|
474
|
+
# 8. Export
|
|
475
|
+
if config.export_csv:
|
|
476
|
+
csv_path = os.path.join(config.output_dir, "bench_results.csv")
|
|
477
|
+
stats_collector.export_csv(csv_path)
|
|
478
|
+
logger.info("CSV results written to %s", csv_path)
|
|
479
|
+
if config.export_json:
|
|
480
|
+
json_path = os.path.join(
|
|
481
|
+
config.output_dir,
|
|
482
|
+
"bench_summary.json",
|
|
483
|
+
)
|
|
484
|
+
stats_collector.export_json(json_path, config)
|
|
485
|
+
logger.info("JSON summary written to %s", json_path)
|
|
486
|
+
|
|
487
|
+
# 9. Exit code
|
|
488
|
+
if final.failed_requests > 0:
|
|
489
|
+
sys.exit(1)
|
|
490
|
+
|
|
491
|
+
def _emit_final_metrics(
|
|
492
|
+
self,
|
|
493
|
+
config: EngineBenchConfig,
|
|
494
|
+
final: FinalStats,
|
|
495
|
+
args: argparse.Namespace,
|
|
496
|
+
) -> None:
|
|
497
|
+
"""Emit final benchmark summary using the CLI metrics system."""
|
|
498
|
+
title = f"Engine Benchmark Result ({config.workload})"
|
|
499
|
+
metrics = self.create_metrics(title, args, width=56)
|
|
500
|
+
|
|
501
|
+
cfg_section = metrics.add_section("config", "Configuration")
|
|
502
|
+
cfg_section.add("engine_url", "Engine URL", config.engine_url)
|
|
503
|
+
cfg_section.add("model", "Model", config.model)
|
|
504
|
+
cfg_section.add("workload", "Workload", config.workload)
|
|
505
|
+
|
|
506
|
+
results = metrics.add_section("results", "Results")
|
|
507
|
+
results.add(
|
|
508
|
+
"successful",
|
|
509
|
+
"Successful requests",
|
|
510
|
+
final.successful_requests,
|
|
511
|
+
)
|
|
512
|
+
results.add("failed", "Failed requests", final.failed_requests)
|
|
513
|
+
results.add(
|
|
514
|
+
"duration",
|
|
515
|
+
"Benchmark duration (s)",
|
|
516
|
+
round(final.elapsed_time, 2),
|
|
517
|
+
)
|
|
518
|
+
results.add(
|
|
519
|
+
"input_tokens",
|
|
520
|
+
"Total input tokens",
|
|
521
|
+
final.total_input_tokens,
|
|
522
|
+
)
|
|
523
|
+
results.add(
|
|
524
|
+
"output_tokens",
|
|
525
|
+
"Total output tokens",
|
|
526
|
+
final.total_output_tokens,
|
|
527
|
+
)
|
|
528
|
+
results.add(
|
|
529
|
+
"input_tput",
|
|
530
|
+
"Input throughput (tok/s)",
|
|
531
|
+
round(final.input_throughput, 2),
|
|
532
|
+
)
|
|
533
|
+
results.add(
|
|
534
|
+
"output_tput",
|
|
535
|
+
"Output throughput (tok/s)",
|
|
536
|
+
round(final.output_throughput, 2),
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
ttft = metrics.add_section("ttft", "Time to First Token")
|
|
540
|
+
ttft.add("mean", "Mean TTFT (ms)", round(final.mean_ttft_ms, 2))
|
|
541
|
+
ttft.add("p50", "P50 TTFT (ms)", round(final.p50_ttft_ms, 2))
|
|
542
|
+
ttft.add("p90", "P90 TTFT (ms)", round(final.p90_ttft_ms, 2))
|
|
543
|
+
ttft.add("p99", "P99 TTFT (ms)", round(final.p99_ttft_ms, 2))
|
|
544
|
+
|
|
545
|
+
decode = metrics.add_section("decode", "Decoding Speed")
|
|
546
|
+
decode.add(
|
|
547
|
+
"mean",
|
|
548
|
+
"Mean decode (tok/s)",
|
|
549
|
+
round(final.mean_decode_speed, 2),
|
|
550
|
+
)
|
|
551
|
+
decode.add(
|
|
552
|
+
"p99",
|
|
553
|
+
"P99 decode (tok/s)",
|
|
554
|
+
round(final.p99_decode_speed, 2),
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
metrics.emit()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|