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,248 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
Defines the data structures that will be used by the
|
|
4
|
+
distributed storage manager public functions
|
|
5
|
+
|
|
6
|
+
Could be implemented by native code in the future
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# Standard
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
|
|
12
|
+
# Third Party
|
|
13
|
+
import torch
|
|
14
|
+
|
|
15
|
+
# First Party
|
|
16
|
+
from lmcache.logging import init_logger
|
|
17
|
+
from lmcache.v1.multiprocess.custom_types import IPCCacheEngineKey
|
|
18
|
+
|
|
19
|
+
logger = init_logger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(frozen=True)
|
|
23
|
+
class ObjectKey:
|
|
24
|
+
"""
|
|
25
|
+
The unique identifier for an object in the distributed storage manager
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
chunk_hash: bytes
|
|
29
|
+
""" Content hash of this particular chunk """
|
|
30
|
+
|
|
31
|
+
model_name: str
|
|
32
|
+
""" Name of the model this chunk belongs to.
|
|
33
|
+
|
|
34
|
+
Invariant: must not contain ``@``. The L2 adapters use ``@`` as the
|
|
35
|
+
field separator in serialized keys/filenames and rely on this
|
|
36
|
+
invariant for unambiguous parsing. HuggingFace model IDs use
|
|
37
|
+
alphanumerics + ``/-_.`` so this rejects nothing that appears in
|
|
38
|
+
practice.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
kv_rank: int
|
|
42
|
+
""" The rank that uniquely identifies the slice of the KV cache """
|
|
43
|
+
|
|
44
|
+
cache_salt: str = ""
|
|
45
|
+
""" Per-user isolation salt. Same content from different users with
|
|
46
|
+
different cache_salt values produces different ObjectKeys, giving
|
|
47
|
+
strict per-user cache isolation. Defaults to empty string, in which
|
|
48
|
+
case serialized keys and filenames match the pre-cache_salt shape
|
|
49
|
+
(no trailing salt field) — no migration is needed for un-salted
|
|
50
|
+
deployments.
|
|
51
|
+
|
|
52
|
+
Invariant: must not contain ``@``, ``/``, ``\\``, or NUL. The L2
|
|
53
|
+
adapters use ``@`` as the field separator; ``/`` and ``\\`` are
|
|
54
|
+
filesystem path separators (FS adapter embeds the salt into
|
|
55
|
+
filenames); NUL terminates C strings (C++ connector). Max length
|
|
56
|
+
128 to stay well within ``NAME_MAX`` (255) after the model, rank,
|
|
57
|
+
hash, and extension are added.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
_SALT_FORBIDDEN_CHARS = frozenset("@/\\\x00")
|
|
61
|
+
_SALT_MAX_LEN = 128
|
|
62
|
+
|
|
63
|
+
def __post_init__(self) -> None:
|
|
64
|
+
if "@" in self.model_name:
|
|
65
|
+
raise ValueError(
|
|
66
|
+
f"model_name must not contain '@' (got {self.model_name!r})"
|
|
67
|
+
)
|
|
68
|
+
bad = self._SALT_FORBIDDEN_CHARS & set(self.cache_salt)
|
|
69
|
+
if bad:
|
|
70
|
+
raise ValueError(
|
|
71
|
+
f"cache_salt must not contain {bad!r} (got {self.cache_salt!r})"
|
|
72
|
+
)
|
|
73
|
+
if len(self.cache_salt) > self._SALT_MAX_LEN:
|
|
74
|
+
raise ValueError(
|
|
75
|
+
f"cache_salt exceeds max length {self._SALT_MAX_LEN} "
|
|
76
|
+
f"(got {len(self.cache_salt)})"
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
@staticmethod
|
|
80
|
+
def IntHash2Bytes(chunk_hash: int) -> bytes:
|
|
81
|
+
# NOTE: this is only used by tests
|
|
82
|
+
return chunk_hash.to_bytes(4, byteorder="big")
|
|
83
|
+
|
|
84
|
+
@staticmethod
|
|
85
|
+
def Bytes2IntHash(chunk_hash: bytes) -> int:
|
|
86
|
+
# NOTE: this is only used by tests
|
|
87
|
+
return int.from_bytes(chunk_hash, byteorder="big") & ((1 << 64) - 1)
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
def ComputeKVRank(
|
|
91
|
+
world_size: int,
|
|
92
|
+
global_rank: int,
|
|
93
|
+
local_world_size: int,
|
|
94
|
+
local_rank: int,
|
|
95
|
+
) -> int:
|
|
96
|
+
"""
|
|
97
|
+
Compute the kv_rank from world_size and worker_id
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
world_size (int): The total number of workers (include TP + PP)
|
|
101
|
+
global_rank (int): The global worker id (from 0 to world_size - 1)
|
|
102
|
+
local_world_size (int): The local world size (for local node),
|
|
103
|
+
should NOT be greater than 8
|
|
104
|
+
local_rank (int): The local world rank (for local node)
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
The special KV rank (bitmap) used by the objectkey
|
|
108
|
+
|
|
109
|
+
Example:
|
|
110
|
+
In the case of TP=4, PP=2, the TP worker 1 on node 1 has:
|
|
111
|
+
- world_size = 8
|
|
112
|
+
- global_rank = 5
|
|
113
|
+
- local_world_size = 4
|
|
114
|
+
- local_rank = 1
|
|
115
|
+
|
|
116
|
+
The output KV rank is the bitmap:
|
|
117
|
+
+--head--+
|
|
118
|
+
|00000000|
|
|
119
|
+
|00000000|
|
|
120
|
+
|00000000|
|
|
121
|
+
|00000000| layers
|
|
122
|
+
|00001100|
|
|
123
|
+
|00001100|
|
|
124
|
+
|00001100|
|
|
125
|
+
|00001100|
|
|
126
|
+
+--------+
|
|
127
|
+
"""
|
|
128
|
+
# TODO(ApostaC): in the long run, we want to have the above bitmap based
|
|
129
|
+
# representation for asymmetric parallelism (e.g., sharing across different
|
|
130
|
+
# TP/PP settings).
|
|
131
|
+
# For now, let's have a simple implementation that just
|
|
132
|
+
# differentiate between different parallel setups
|
|
133
|
+
|
|
134
|
+
# For each number, we use 8-bit, and pack them together
|
|
135
|
+
return (
|
|
136
|
+
(world_size << 24)
|
|
137
|
+
| (global_rank << 16)
|
|
138
|
+
| (local_world_size << 8)
|
|
139
|
+
| local_rank
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@dataclass(frozen=True)
|
|
144
|
+
class MemoryLayoutDesc:
|
|
145
|
+
"""
|
|
146
|
+
Describes the layout of a memory object
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
shapes: list[torch.Size]
|
|
150
|
+
dtypes: list[torch.dtype]
|
|
151
|
+
|
|
152
|
+
def __post_init__(self):
|
|
153
|
+
if len(self.shapes) != len(self.dtypes):
|
|
154
|
+
raise ValueError(
|
|
155
|
+
"MemoryLayoutDesc: shapes and dtype must have the same length"
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@dataclass(frozen=True)
|
|
160
|
+
class PrefetchHandle:
|
|
161
|
+
"""Opaque handle returned by ``StorageManager.submit_prefetch_task``.
|
|
162
|
+
|
|
163
|
+
Carries the bookkeeping needed to later query lookup / prefetch status
|
|
164
|
+
without exposing controller internals.
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
prefetch_request_id: int
|
|
168
|
+
"""Opaque ID for tracking L2 prefetch in the controller.
|
|
169
|
+
-1 if no L2 request was submitted."""
|
|
170
|
+
|
|
171
|
+
external_request_id: str
|
|
172
|
+
"""Request ID from the caller for end-to-end tracing."""
|
|
173
|
+
|
|
174
|
+
l1_prefix_hit_count: int
|
|
175
|
+
"""Number of leading keys already in L1 at submission time."""
|
|
176
|
+
|
|
177
|
+
total_requested_keys: int
|
|
178
|
+
"""Total number of keys originally requested."""
|
|
179
|
+
|
|
180
|
+
submit_time: float
|
|
181
|
+
"""Monotonic timestamp when the prefetch task was submitted."""
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def ipc_key_to_object_keys(
|
|
185
|
+
ipc_key: IPCCacheEngineKey,
|
|
186
|
+
chunk_hashes: list[bytes],
|
|
187
|
+
) -> list[ObjectKey]:
|
|
188
|
+
"""
|
|
189
|
+
Convert a single IPCCacheEngineKey and its chunk hashes to a list of ObjectKey.
|
|
190
|
+
|
|
191
|
+
When the ipc_key's worker_id is None, each chunk hash is exploded into
|
|
192
|
+
multiple ObjectKeys (one per worker in world_size).
|
|
193
|
+
|
|
194
|
+
``cache_salt`` is read directly from ``ipc_key`` so the produced
|
|
195
|
+
ObjectKeys are per-user isolated whenever the sender set a non-empty
|
|
196
|
+
salt. There is intentionally no separate ``cache_salt`` parameter —
|
|
197
|
+
duplicating the source of truth would risk silent isolation bugs
|
|
198
|
+
where a caller passes ``ipc_key`` but forgets the salt.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
ipc_key: The IPC key providing model_name, world_size, worker_id,
|
|
202
|
+
and cache_salt.
|
|
203
|
+
chunk_hashes: List of chunk hash bytes, one per chunk.
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
list[ObjectKey]: The converted list of ObjectKey.
|
|
207
|
+
"""
|
|
208
|
+
cache_salt = ipc_key.cache_salt
|
|
209
|
+
storage_keys = []
|
|
210
|
+
for chunk_hash in chunk_hashes:
|
|
211
|
+
if ipc_key.worker_id is None:
|
|
212
|
+
# For look up request, we want to expand to all workers
|
|
213
|
+
for worker_id in range(ipc_key.world_size):
|
|
214
|
+
# TODO (ApostaC): include local world size/rank info
|
|
215
|
+
# in the future once it's in IPCCacheEngineKey
|
|
216
|
+
kv_rank = ObjectKey.ComputeKVRank(
|
|
217
|
+
world_size=ipc_key.world_size,
|
|
218
|
+
global_rank=worker_id,
|
|
219
|
+
local_world_size=ipc_key.world_size,
|
|
220
|
+
local_rank=worker_id,
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
storage_keys.append(
|
|
224
|
+
ObjectKey(
|
|
225
|
+
chunk_hash=chunk_hash,
|
|
226
|
+
model_name=ipc_key.model_name,
|
|
227
|
+
kv_rank=kv_rank,
|
|
228
|
+
cache_salt=cache_salt,
|
|
229
|
+
)
|
|
230
|
+
)
|
|
231
|
+
else:
|
|
232
|
+
kv_rank = ObjectKey.ComputeKVRank(
|
|
233
|
+
world_size=ipc_key.world_size,
|
|
234
|
+
global_rank=ipc_key.worker_id,
|
|
235
|
+
local_world_size=ipc_key.world_size,
|
|
236
|
+
local_rank=ipc_key.worker_id,
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
storage_keys.append(
|
|
240
|
+
ObjectKey(
|
|
241
|
+
chunk_hash=chunk_hash,
|
|
242
|
+
model_name=ipc_key.model_name,
|
|
243
|
+
kv_rank=kv_rank,
|
|
244
|
+
cache_salt=cache_salt,
|
|
245
|
+
)
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
return storage_keys
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Configuration for distributed storage manager
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# Standard
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from typing import Literal
|
|
10
|
+
import argparse
|
|
11
|
+
|
|
12
|
+
# First Party
|
|
13
|
+
from lmcache.v1.distributed.l2_adapters.config import (
|
|
14
|
+
L2AdaptersConfig,
|
|
15
|
+
add_l2_adapters_args,
|
|
16
|
+
parse_args_to_l2_adapters_config,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class L1MemoryManagerConfig:
|
|
22
|
+
"""
|
|
23
|
+
The configuration for L1 memory manager.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
size_in_bytes: int
|
|
27
|
+
""" The size of L1 memory in bytes. """
|
|
28
|
+
|
|
29
|
+
use_lazy: bool
|
|
30
|
+
""" Whether to use lazy initialization for L1 memory. """
|
|
31
|
+
|
|
32
|
+
init_size_in_bytes: int = field(default=20 << 30)
|
|
33
|
+
""" The initial size when using lazy allocation. Default is 20GB. """
|
|
34
|
+
|
|
35
|
+
align_bytes: int = field(default=0x1000)
|
|
36
|
+
""" The alignment size in bytes. Default is 4KB. """
|
|
37
|
+
|
|
38
|
+
def __post_init__(self):
|
|
39
|
+
self.init_size_in_bytes = min(self.init_size_in_bytes, self.size_in_bytes)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class L1ManagerConfig:
|
|
44
|
+
"""
|
|
45
|
+
Special config for the L1 Object/Key manager
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
memory_config: L1MemoryManagerConfig
|
|
49
|
+
""" The memory manager configuration for L1 cache. """
|
|
50
|
+
|
|
51
|
+
write_ttl_seconds: int = field(default=600)
|
|
52
|
+
""" Time to live for each object's write lock. Default is 600s (10 minutes). """
|
|
53
|
+
|
|
54
|
+
read_ttl_seconds: int = field(default=300)
|
|
55
|
+
""" Time to live for each object's read lock. Default is 300s (5 minutes). """
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass
|
|
59
|
+
class EvictionConfig:
|
|
60
|
+
"""
|
|
61
|
+
The configuration for eviction policies (L1 and optionally L2).
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
eviction_policy: Literal["LRU", "noop"]
|
|
65
|
+
""" The eviction policy to use. """
|
|
66
|
+
|
|
67
|
+
trigger_watermark: float = field(default=0.8)
|
|
68
|
+
""" The memory usage watermark to trigger eviction (0.0 to 1.0). """
|
|
69
|
+
|
|
70
|
+
eviction_ratio: float = field(default=0.2)
|
|
71
|
+
""" The fraction of *allocated* memory to evict when triggered (0.0 to 1.0). """
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@dataclass
|
|
75
|
+
class StorageManagerConfig:
|
|
76
|
+
"""
|
|
77
|
+
The configuration for the distributed storage manager.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
l1_manager_config: L1ManagerConfig
|
|
81
|
+
""" The configuration for the L1 manager. """
|
|
82
|
+
|
|
83
|
+
eviction_config: EvictionConfig
|
|
84
|
+
""" The configuration for eviction policies. """
|
|
85
|
+
|
|
86
|
+
l2_adapter_config: L2AdaptersConfig = field(
|
|
87
|
+
default_factory=lambda: L2AdaptersConfig([])
|
|
88
|
+
)
|
|
89
|
+
""" The configuration for L2 adapters. """
|
|
90
|
+
|
|
91
|
+
store_policy: str = "default"
|
|
92
|
+
""" The L2 store policy name. """
|
|
93
|
+
|
|
94
|
+
prefetch_policy: str = "default"
|
|
95
|
+
""" The L2 prefetch policy name. """
|
|
96
|
+
|
|
97
|
+
prefetch_max_in_flight: int = 8
|
|
98
|
+
""" Maximum number of concurrent prefetch requests. """
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def add_storage_manager_args(
|
|
102
|
+
parser: argparse.ArgumentParser,
|
|
103
|
+
) -> argparse.ArgumentParser:
|
|
104
|
+
"""
|
|
105
|
+
Add storage manager configuration arguments to an existing parser.
|
|
106
|
+
|
|
107
|
+
This function allows other modules to integrate storage manager arguments
|
|
108
|
+
into their own argument parsers. Arguments are organized into groups to
|
|
109
|
+
avoid naming conflicts with other modules.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
parser: The argument parser to add arguments to.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
argparse.ArgumentParser: The same parser with storage manager
|
|
116
|
+
arguments added.
|
|
117
|
+
|
|
118
|
+
Example:
|
|
119
|
+
>>> # In another module that needs its own arguments
|
|
120
|
+
>>> parser = argparse.ArgumentParser(description="My Application")
|
|
121
|
+
>>> parser.add_argument("--my-arg", type=str)
|
|
122
|
+
>>> add_storage_manager_args(parser)
|
|
123
|
+
>>> args = parser.parse_args()
|
|
124
|
+
>>> config = parse_args_to_config(args)
|
|
125
|
+
"""
|
|
126
|
+
# L1 Memory Manager Config
|
|
127
|
+
memory_group = parser.add_argument_group(
|
|
128
|
+
"L1 Memory Manager", "Configuration for L1 memory manager"
|
|
129
|
+
)
|
|
130
|
+
memory_group.add_argument(
|
|
131
|
+
"--l1-size-gb",
|
|
132
|
+
type=float,
|
|
133
|
+
required=True,
|
|
134
|
+
help="The size of L1 memory in GB.",
|
|
135
|
+
)
|
|
136
|
+
memory_group.add_argument(
|
|
137
|
+
"--l1-use-lazy",
|
|
138
|
+
action=argparse.BooleanOptionalAction,
|
|
139
|
+
default=True,
|
|
140
|
+
help="Whether to use lazy loading for L1 memory. (Default is True)",
|
|
141
|
+
)
|
|
142
|
+
memory_group.add_argument(
|
|
143
|
+
"--l1-init-size-gb",
|
|
144
|
+
type=int,
|
|
145
|
+
default=20,
|
|
146
|
+
help="The initial size (GB) when using lazy allocation. Default is 20.",
|
|
147
|
+
)
|
|
148
|
+
memory_group.add_argument(
|
|
149
|
+
"--l1-align-bytes",
|
|
150
|
+
type=int,
|
|
151
|
+
default=4096,
|
|
152
|
+
help="The alignment size in bytes. Default is 4KB (4096 bytes).",
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# L1 Manager Config (TTL settings)
|
|
156
|
+
ttl_group = parser.add_argument_group(
|
|
157
|
+
"L1 Manager TTL", "TTL configuration for L1 manager locks"
|
|
158
|
+
)
|
|
159
|
+
ttl_group.add_argument(
|
|
160
|
+
"--l1-write-ttl-seconds",
|
|
161
|
+
type=int,
|
|
162
|
+
default=600,
|
|
163
|
+
help="Time to live for each object's write lock. Default is 600s.",
|
|
164
|
+
)
|
|
165
|
+
ttl_group.add_argument(
|
|
166
|
+
"--l1-read-ttl-seconds",
|
|
167
|
+
type=int,
|
|
168
|
+
default=300,
|
|
169
|
+
help="Time to live for each object's read lock. Default is 300s.",
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# Eviction Config
|
|
173
|
+
eviction_group = parser.add_argument_group(
|
|
174
|
+
"Eviction Policy", "Configuration for eviction policies"
|
|
175
|
+
)
|
|
176
|
+
eviction_group.add_argument(
|
|
177
|
+
"--eviction-policy",
|
|
178
|
+
type=str,
|
|
179
|
+
choices=["LRU", "noop"],
|
|
180
|
+
required=True,
|
|
181
|
+
help="The eviction policy to use ('LRU' or 'noop').",
|
|
182
|
+
)
|
|
183
|
+
eviction_group.add_argument(
|
|
184
|
+
"--eviction-trigger-watermark",
|
|
185
|
+
type=float,
|
|
186
|
+
default=0.8,
|
|
187
|
+
help="The memory usage watermark to trigger eviction (0.0 to 1.0). "
|
|
188
|
+
"Default is 0.8.",
|
|
189
|
+
)
|
|
190
|
+
eviction_group.add_argument(
|
|
191
|
+
"--eviction-ratio",
|
|
192
|
+
type=float,
|
|
193
|
+
default=0.2,
|
|
194
|
+
help="The fraction of memory to evict when triggered (0.0 to 1.0). "
|
|
195
|
+
"Default is 0.2.",
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
# L2 Policies
|
|
199
|
+
# Import here to break circular dependency:
|
|
200
|
+
# config.py <-> storage_controllers (via eviction_controller)
|
|
201
|
+
# Safe because config.py is fully initialized by the time this
|
|
202
|
+
# function is called.
|
|
203
|
+
# First Party
|
|
204
|
+
from lmcache.v1.distributed.storage_controllers.prefetch_policy import (
|
|
205
|
+
get_registered_prefetch_policies,
|
|
206
|
+
)
|
|
207
|
+
from lmcache.v1.distributed.storage_controllers.store_policy import (
|
|
208
|
+
get_registered_store_policies,
|
|
209
|
+
)
|
|
210
|
+
import lmcache.v1.distributed.storage_controllers # noqa: F401
|
|
211
|
+
|
|
212
|
+
policy_group = parser.add_argument_group(
|
|
213
|
+
"L2 Policies", "Store and prefetch policy selection for L2 adapters"
|
|
214
|
+
)
|
|
215
|
+
policy_group.add_argument(
|
|
216
|
+
"--l2-store-policy",
|
|
217
|
+
type=str,
|
|
218
|
+
choices=get_registered_store_policies(),
|
|
219
|
+
default="default",
|
|
220
|
+
help="L2 store policy. Determines which adapters receive each key "
|
|
221
|
+
"and whether keys are deleted from L1 after L2 store. "
|
|
222
|
+
"Default is 'default' (store all keys to all adapters, keep L1).",
|
|
223
|
+
)
|
|
224
|
+
policy_group.add_argument(
|
|
225
|
+
"--l2-prefetch-policy",
|
|
226
|
+
type=str,
|
|
227
|
+
choices=get_registered_prefetch_policies(),
|
|
228
|
+
default="default",
|
|
229
|
+
help="L2 prefetch policy. Determines which adapter loads each key "
|
|
230
|
+
"when multiple adapters have it. "
|
|
231
|
+
"Default is 'default' (pick the first adapter by index).",
|
|
232
|
+
)
|
|
233
|
+
policy_group.add_argument(
|
|
234
|
+
"--l2-prefetch-max-in-flight",
|
|
235
|
+
type=int,
|
|
236
|
+
default=8,
|
|
237
|
+
help="Maximum number of concurrent prefetch requests. Default is 8.",
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
# Adapter config
|
|
241
|
+
add_l2_adapters_args(parser)
|
|
242
|
+
return parser
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def get_arg_parser() -> argparse.ArgumentParser:
|
|
246
|
+
"""
|
|
247
|
+
Get a standalone argument parser for storage manager configuration.
|
|
248
|
+
|
|
249
|
+
This creates a new parser with only storage manager arguments.
|
|
250
|
+
For integrating with other modules' parsers, use add_storage_manager_args()
|
|
251
|
+
instead.
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
argparse.ArgumentParser: The argument parser with all storage manager
|
|
255
|
+
configuration options.
|
|
256
|
+
"""
|
|
257
|
+
parser = argparse.ArgumentParser(
|
|
258
|
+
description="Distributed Storage Manager Configuration"
|
|
259
|
+
)
|
|
260
|
+
return add_storage_manager_args(parser)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def parse_args_to_config(
|
|
264
|
+
args: argparse.Namespace,
|
|
265
|
+
) -> StorageManagerConfig:
|
|
266
|
+
"""
|
|
267
|
+
Convert parsed command line arguments to a StorageManagerConfig.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
args: Parsed arguments from the argument parser.
|
|
271
|
+
|
|
272
|
+
Returns:
|
|
273
|
+
StorageManagerConfig: The configuration object.
|
|
274
|
+
"""
|
|
275
|
+
memory_config = L1MemoryManagerConfig(
|
|
276
|
+
size_in_bytes=int(args.l1_size_gb * (1 << 30)),
|
|
277
|
+
use_lazy=args.l1_use_lazy,
|
|
278
|
+
init_size_in_bytes=int(args.l1_init_size_gb * (1 << 30)),
|
|
279
|
+
align_bytes=args.l1_align_bytes,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
l1_manager_config = L1ManagerConfig(
|
|
283
|
+
memory_config=memory_config,
|
|
284
|
+
write_ttl_seconds=args.l1_write_ttl_seconds,
|
|
285
|
+
read_ttl_seconds=args.l1_read_ttl_seconds,
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
eviction_config = EvictionConfig(
|
|
289
|
+
eviction_policy=args.eviction_policy,
|
|
290
|
+
trigger_watermark=args.eviction_trigger_watermark,
|
|
291
|
+
eviction_ratio=args.eviction_ratio,
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
l2_adapter_config = parse_args_to_l2_adapters_config(args)
|
|
295
|
+
|
|
296
|
+
return StorageManagerConfig(
|
|
297
|
+
l1_manager_config=l1_manager_config,
|
|
298
|
+
eviction_config=eviction_config,
|
|
299
|
+
l2_adapter_config=l2_adapter_config,
|
|
300
|
+
store_policy=args.l2_store_policy,
|
|
301
|
+
prefetch_policy=args.l2_prefetch_policy,
|
|
302
|
+
prefetch_max_in_flight=args.l2_prefetch_max_in_flight,
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def parse_args(args: list[str] | None = None) -> StorageManagerConfig:
|
|
307
|
+
"""
|
|
308
|
+
Parse command line arguments and return a StorageManagerConfig.
|
|
309
|
+
|
|
310
|
+
This is a convenience function that combines get_arg_parser() and
|
|
311
|
+
parse_args_to_config().
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
args: Optional list of arguments to parse. If None, uses sys.argv.
|
|
315
|
+
|
|
316
|
+
Returns:
|
|
317
|
+
StorageManagerConfig: The configuration object.
|
|
318
|
+
"""
|
|
319
|
+
parser = get_arg_parser()
|
|
320
|
+
parsed_args = parser.parse_args(args)
|
|
321
|
+
return parse_args_to_config(parsed_args)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Definition of errors for class APIs.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# Standard
|
|
8
|
+
import enum
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class L1Error(enum.Enum):
|
|
12
|
+
"""Errors for L1Manager class APIs."""
|
|
13
|
+
|
|
14
|
+
SUCCESS = enum.auto()
|
|
15
|
+
""" Operation succeeded. """
|
|
16
|
+
|
|
17
|
+
KEY_NOT_EXIST = enum.auto()
|
|
18
|
+
""" The specified key does not exist. """
|
|
19
|
+
|
|
20
|
+
KEY_NOT_READABLE = enum.auto()
|
|
21
|
+
""" The specified key exists but cannot be read """
|
|
22
|
+
|
|
23
|
+
KEY_NOT_WRITABLE = enum.auto()
|
|
24
|
+
""" The specified key exists but cannot be written """
|
|
25
|
+
|
|
26
|
+
KEY_IN_WRONG_STATE = enum.auto()
|
|
27
|
+
""" The specified key is in the wrong state for the operation. """
|
|
28
|
+
|
|
29
|
+
KEY_IS_LOCKED = enum.auto()
|
|
30
|
+
""" The specified key is locked and cannot perform the operation. """
|
|
31
|
+
|
|
32
|
+
OUT_OF_MEMORY = enum.auto()
|
|
33
|
+
""" Not enough memory to complete the operation. """
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
ErrorType = L1Error
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def strerror(error: ErrorType) -> str:
|
|
40
|
+
"""Convert error code to human-readable string.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
error (ErrorType): The error code.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
str: The human-readable string.
|
|
47
|
+
"""
|
|
48
|
+
if isinstance(error, L1Error):
|
|
49
|
+
if error == L1Error.SUCCESS:
|
|
50
|
+
return "Operation succeeded."
|
|
51
|
+
elif error == L1Error.KEY_NOT_EXIST:
|
|
52
|
+
return "The specified key does not exist."
|
|
53
|
+
elif error == L1Error.KEY_NOT_READABLE:
|
|
54
|
+
return "The specified key exists but cannot be read."
|
|
55
|
+
elif error == L1Error.KEY_NOT_WRITABLE:
|
|
56
|
+
return "The specified key exists but cannot be written."
|
|
57
|
+
elif error == L1Error.KEY_IN_WRONG_STATE:
|
|
58
|
+
return "The specified key is in the wrong state for the operation."
|
|
59
|
+
elif error == L1Error.KEY_IS_LOCKED:
|
|
60
|
+
return "The specified key is locked and cannot perform the operation."
|
|
61
|
+
elif error == L1Error.OUT_OF_MEMORY:
|
|
62
|
+
return "Not enough memory to complete the operation."
|
|
63
|
+
|
|
64
|
+
return "Unknown error."
|