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,192 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
Eviction module to determine what to evict from L1 and L2 caches.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# Standard
|
|
7
|
+
from abc import abstractmethod
|
|
8
|
+
from collections.abc import Callable
|
|
9
|
+
|
|
10
|
+
# First Party
|
|
11
|
+
from lmcache.v1.distributed.api import ObjectKey
|
|
12
|
+
from lmcache.v1.distributed.internal_api import (
|
|
13
|
+
EvictionAction,
|
|
14
|
+
EvictionDestination,
|
|
15
|
+
L1ManagerListener,
|
|
16
|
+
L2AdapterListener,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class EvictionPolicy:
|
|
21
|
+
"""
|
|
22
|
+
Pure abstract base class for eviction policies.
|
|
23
|
+
|
|
24
|
+
Subclasses implement the LRU (or other) tracking logic via the
|
|
25
|
+
on_keys_* methods and expose eviction decisions via get_eviction_actions.
|
|
26
|
+
The binding to a specific cache tier (L1 or L2) is provided by
|
|
27
|
+
L1EvictionPolicy and L2EvictionPolicy respectively.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def support_isolation(self) -> bool:
|
|
32
|
+
"""Whether this policy supports isolation eviction (e.g., per user isolation).
|
|
33
|
+
|
|
34
|
+
When True, the eviction controller checks isolated usage (e.g., per user usage)
|
|
35
|
+
and passes ``cache_salt`` to ``get_eviction_actions()`` to scope
|
|
36
|
+
eviction to specific cache_salt. When False, the controller uses
|
|
37
|
+
aggregate usage only.
|
|
38
|
+
|
|
39
|
+
Default is False. Subclasses that support isolated eviction.
|
|
40
|
+
(e.g., ``IsolatedLRUEvictionPolicy``) should override to return True.
|
|
41
|
+
"""
|
|
42
|
+
return False
|
|
43
|
+
|
|
44
|
+
@abstractmethod
|
|
45
|
+
def register_eviction_destination(self, destination: EvictionDestination):
|
|
46
|
+
"""
|
|
47
|
+
Register an eviction destination for the eviction policy to use.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
destination (EvictionDestination): The eviction destination to
|
|
51
|
+
register.
|
|
52
|
+
"""
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
@abstractmethod
|
|
56
|
+
def on_keys_created(self, keys: list[ObjectKey]):
|
|
57
|
+
"""
|
|
58
|
+
Notify the eviction policy that new keys have been created.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
keys (list[ObjectKey]): The keys that have been created.
|
|
62
|
+
"""
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
@abstractmethod
|
|
66
|
+
def on_keys_touched(self, keys: list[ObjectKey]):
|
|
67
|
+
"""
|
|
68
|
+
Notify the eviction policy that keys have been accessed.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
keys (list[ObjectKey]): The keys that have been accessed.
|
|
72
|
+
"""
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
@abstractmethod
|
|
76
|
+
def on_keys_removed(self, keys: list[ObjectKey]):
|
|
77
|
+
"""
|
|
78
|
+
Notify the eviction policy that keys have been deleted.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
keys (list[ObjectKey]): The keys that have been deleted.
|
|
82
|
+
"""
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
@abstractmethod
|
|
86
|
+
def get_eviction_actions(
|
|
87
|
+
self,
|
|
88
|
+
expected_ratio: float,
|
|
89
|
+
key_eligible_filter: Callable[[ObjectKey], bool] | None = None,
|
|
90
|
+
cache_salt: str | None = None,
|
|
91
|
+
) -> list[EvictionAction]:
|
|
92
|
+
"""
|
|
93
|
+
Get the eviction actions to evict objects from cache.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
expected_ratio (float): A hint indicating approximately what
|
|
97
|
+
fraction of tracked keys should be evicted. Value should be
|
|
98
|
+
in range [0.0, 1.0]. For example, 0.1 means roughly 10% of
|
|
99
|
+
keys should be evicted. This is a hint and the policy may
|
|
100
|
+
return more or fewer keys.
|
|
101
|
+
key_eligible_filter: An optional callable that takes an ObjectKey
|
|
102
|
+
and returns True if the key is eligible for eviction. When
|
|
103
|
+
provided, keys for which the filter returns False will be
|
|
104
|
+
skipped. This is useful for skipping locked keys that
|
|
105
|
+
cannot be deleted.
|
|
106
|
+
cache_salt: When set, scope eviction to keys belonging to this
|
|
107
|
+
salt only (identified by ``ObjectKey.cache_salt``). When
|
|
108
|
+
None, evict globally across all salts. Only meaningful for
|
|
109
|
+
policies where ``support_isolation`` is True; other policies
|
|
110
|
+
ignore this parameter.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
list[EvictionAction]: The eviction actions to perform. Each
|
|
114
|
+
action contains the keys and one eviction destination.
|
|
115
|
+
|
|
116
|
+
Notes:
|
|
117
|
+
The eviction action may not be successfully executed, or it may
|
|
118
|
+
be executed asynchronously. Therefore, the eviction policy should
|
|
119
|
+
not assume that the objects are evicted immediately, but it should
|
|
120
|
+
use `on_keys_removed` to know when the objects are actually
|
|
121
|
+
deleted.
|
|
122
|
+
"""
|
|
123
|
+
pass
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class L1EvictionPolicy(L1ManagerListener):
|
|
127
|
+
"""
|
|
128
|
+
Bridges L1Manager lifecycle events to an EvictionPolicy instance.
|
|
129
|
+
|
|
130
|
+
The actual eviction policy is provided via the constructor, keeping
|
|
131
|
+
the policy logic decoupled from the listener interface.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
def __init__(self, policy: EvictionPolicy):
|
|
135
|
+
self._policy = policy
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def policy(self) -> EvictionPolicy:
|
|
139
|
+
return self._policy
|
|
140
|
+
|
|
141
|
+
# L1ManagerListener implementations
|
|
142
|
+
def on_l1_keys_reserved_read(self, keys: list[ObjectKey]):
|
|
143
|
+
# No-op
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
def on_l1_keys_read_finished(self, keys: list[ObjectKey]):
|
|
147
|
+
self._policy.on_keys_touched(keys)
|
|
148
|
+
|
|
149
|
+
def on_l1_keys_reserved_write(self, keys: list[ObjectKey]):
|
|
150
|
+
# No-op
|
|
151
|
+
pass
|
|
152
|
+
|
|
153
|
+
def on_l1_keys_write_finished(self, keys: list[ObjectKey]):
|
|
154
|
+
# TODO (ApostaC): we don't differentiate between the created keys and
|
|
155
|
+
# updated keys here. Probably need to fix that by introducing a new
|
|
156
|
+
# callback in L1ManagerListener or adding `mode` argument into
|
|
157
|
+
# on_keys_reserved_write.
|
|
158
|
+
self._policy.on_keys_created(keys)
|
|
159
|
+
|
|
160
|
+
def on_l1_keys_deleted_by_manager(self, keys: list[ObjectKey]):
|
|
161
|
+
self._policy.on_keys_removed(keys)
|
|
162
|
+
|
|
163
|
+
def on_l1_keys_finish_write_and_reserve_read(self, keys: list[ObjectKey]):
|
|
164
|
+
self._policy.on_keys_created(keys)
|
|
165
|
+
|
|
166
|
+
def on_l1_keys_accessed(self, keys: list[ObjectKey]):
|
|
167
|
+
self._policy.on_keys_touched(keys)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class L2EvictionPolicy(L2AdapterListener):
|
|
171
|
+
"""
|
|
172
|
+
Bridges L2Adapter lifecycle events to an EvictionPolicy instance.
|
|
173
|
+
|
|
174
|
+
The actual eviction policy is provided via the constructor, keeping
|
|
175
|
+
the policy logic decoupled from the listener interface.
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
def __init__(self, policy: EvictionPolicy):
|
|
179
|
+
self._policy = policy
|
|
180
|
+
|
|
181
|
+
@property
|
|
182
|
+
def policy(self) -> EvictionPolicy:
|
|
183
|
+
return self._policy
|
|
184
|
+
|
|
185
|
+
def on_l2_keys_stored(self, keys: list[ObjectKey]):
|
|
186
|
+
self._policy.on_keys_created(keys)
|
|
187
|
+
|
|
188
|
+
def on_l2_keys_accessed(self, keys: list[ObjectKey]):
|
|
189
|
+
self._policy.on_keys_touched(keys)
|
|
190
|
+
|
|
191
|
+
def on_l2_keys_deleted(self, keys: list[ObjectKey]):
|
|
192
|
+
self._policy.on_keys_removed(keys)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
Eviction policies for L1 cache management
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# First Party
|
|
7
|
+
from lmcache.v1.distributed.eviction_policy.factory import (
|
|
8
|
+
CreateEvictionPolicy,
|
|
9
|
+
)
|
|
10
|
+
from lmcache.v1.distributed.eviction_policy.lru import (
|
|
11
|
+
LRUEvictionPolicy,
|
|
12
|
+
)
|
|
13
|
+
from lmcache.v1.distributed.eviction_policy.noop import (
|
|
14
|
+
NoOpEvictionPolicy,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"LRUEvictionPolicy",
|
|
19
|
+
"NoOpEvictionPolicy",
|
|
20
|
+
"CreateEvictionPolicy",
|
|
21
|
+
]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
# First Party
|
|
4
|
+
from lmcache.v1.distributed.config import EvictionConfig
|
|
5
|
+
from lmcache.v1.distributed.eviction import EvictionPolicy
|
|
6
|
+
from lmcache.v1.distributed.eviction_policy.lru import LRUEvictionPolicy
|
|
7
|
+
from lmcache.v1.distributed.eviction_policy.noop import NoOpEvictionPolicy
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def CreateEvictionPolicy(eviction_config: EvictionConfig) -> EvictionPolicy:
|
|
11
|
+
"""
|
|
12
|
+
Factory method to create an eviction policy based on the provided configuration.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
eviction_config (EvictionConfig): The configuration for the eviction policy.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
An instance of the specified eviction policy.
|
|
19
|
+
"""
|
|
20
|
+
if eviction_config.eviction_policy == "LRU":
|
|
21
|
+
return LRUEvictionPolicy()
|
|
22
|
+
elif eviction_config.eviction_policy == "noop":
|
|
23
|
+
return NoOpEvictionPolicy()
|
|
24
|
+
else:
|
|
25
|
+
raise ValueError(
|
|
26
|
+
f"Unsupported eviction policy: {eviction_config.eviction_policy}"
|
|
27
|
+
)
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
LRU (Least Recently Used) eviction policy implementation
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# Standard
|
|
7
|
+
from collections import OrderedDict
|
|
8
|
+
from collections.abc import Callable
|
|
9
|
+
import threading
|
|
10
|
+
|
|
11
|
+
# First Party
|
|
12
|
+
from lmcache.v1.distributed.api import ObjectKey
|
|
13
|
+
from lmcache.v1.distributed.eviction import EvictionPolicy
|
|
14
|
+
from lmcache.v1.distributed.internal_api import (
|
|
15
|
+
EvictionAction,
|
|
16
|
+
EvictionDestination,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class LRUEvictionPolicy(EvictionPolicy):
|
|
21
|
+
"""
|
|
22
|
+
LRU (Least Recently Used) eviction policy.
|
|
23
|
+
|
|
24
|
+
This policy tracks the order of key accesses and evicts the least recently
|
|
25
|
+
used keys first when eviction is needed.
|
|
26
|
+
|
|
27
|
+
Thread Safety:
|
|
28
|
+
This class is thread-safe. All operations are protected by a global lock
|
|
29
|
+
to ensure eventual consistency without corrupted states.
|
|
30
|
+
|
|
31
|
+
Attributes:
|
|
32
|
+
_lock: Threading lock for thread-safe operations
|
|
33
|
+
_order: OrderedDict maintaining LRU order (most recent at end)
|
|
34
|
+
_destinations: List of registered eviction destinations
|
|
35
|
+
_default_destination: The default destination for eviction actions
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def __init__(
|
|
39
|
+
self,
|
|
40
|
+
default_destination: EvictionDestination = EvictionDestination.DISCARD,
|
|
41
|
+
):
|
|
42
|
+
"""
|
|
43
|
+
Initialize the LRU eviction policy.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
default_destination: The default destination for evicted objects.
|
|
47
|
+
Defaults to DISCARD.
|
|
48
|
+
"""
|
|
49
|
+
# Lock for thread-safe operations
|
|
50
|
+
self._lock = threading.Lock()
|
|
51
|
+
|
|
52
|
+
# OrderedDict to maintain LRU order - keys at the beginning are oldest
|
|
53
|
+
self._order: OrderedDict[ObjectKey, None] = OrderedDict()
|
|
54
|
+
|
|
55
|
+
# List of registered eviction destinations
|
|
56
|
+
self._destinations: list[EvictionDestination] = []
|
|
57
|
+
|
|
58
|
+
# Default destination for eviction
|
|
59
|
+
self._default_destination = default_destination
|
|
60
|
+
|
|
61
|
+
def register_eviction_destination(self, destination: EvictionDestination):
|
|
62
|
+
"""
|
|
63
|
+
Register an eviction destination for the eviction policy to use.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
destination (EvictionDestination): The eviction destination to register
|
|
67
|
+
"""
|
|
68
|
+
with self._lock:
|
|
69
|
+
if destination not in self._destinations:
|
|
70
|
+
self._destinations.append(destination)
|
|
71
|
+
|
|
72
|
+
def on_keys_created(self, keys: list[ObjectKey]):
|
|
73
|
+
"""
|
|
74
|
+
Notify the eviction policy that new keys have been created.
|
|
75
|
+
New keys are added as most recently used.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
keys (list[ObjectKey]): The keys that have been created
|
|
79
|
+
"""
|
|
80
|
+
if not keys:
|
|
81
|
+
return
|
|
82
|
+
with self._lock:
|
|
83
|
+
# NOTE: for the request, the later keys should be evicted first.
|
|
84
|
+
# For example, the request has (key1, key2, key3), if we first
|
|
85
|
+
# evict key1, due to prefix match, key2 and key3 will not be hit.
|
|
86
|
+
for key in reversed(keys):
|
|
87
|
+
# If key already exists, move it to the end (most recently used)
|
|
88
|
+
if key in self._order:
|
|
89
|
+
self._order.move_to_end(key)
|
|
90
|
+
else:
|
|
91
|
+
# Add new key at the end (most recently used)
|
|
92
|
+
self._order[key] = None
|
|
93
|
+
|
|
94
|
+
def on_keys_touched(self, keys: list[ObjectKey]):
|
|
95
|
+
"""
|
|
96
|
+
Notify the eviction policy that keys have been accessed.
|
|
97
|
+
Touched keys are moved to the most recently used position.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
keys (list[ObjectKey]): The keys that have been accessed
|
|
101
|
+
"""
|
|
102
|
+
if not keys:
|
|
103
|
+
return
|
|
104
|
+
with self._lock:
|
|
105
|
+
# NOTE: for the request, the later keys should be evicted first.
|
|
106
|
+
# The example is the same as `on_keys_created`.
|
|
107
|
+
for key in reversed(keys):
|
|
108
|
+
if key in self._order:
|
|
109
|
+
# Move to end (most recently used)
|
|
110
|
+
self._order.move_to_end(key)
|
|
111
|
+
|
|
112
|
+
def on_keys_removed(self, keys: list[ObjectKey]):
|
|
113
|
+
"""
|
|
114
|
+
Notify the eviction policy that keys have been deleted.
|
|
115
|
+
Deleted keys are removed from tracking.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
keys (list[ObjectKey]): The keys that have been deleted
|
|
119
|
+
"""
|
|
120
|
+
if not keys:
|
|
121
|
+
return
|
|
122
|
+
with self._lock:
|
|
123
|
+
for key in keys:
|
|
124
|
+
# Remove from LRU order tracking
|
|
125
|
+
if key in self._order:
|
|
126
|
+
del self._order[key]
|
|
127
|
+
|
|
128
|
+
def get_eviction_actions(
|
|
129
|
+
self,
|
|
130
|
+
expected_ratio: float,
|
|
131
|
+
key_eligible_filter: Callable[[ObjectKey], bool] | None = None,
|
|
132
|
+
cache_salt: str | None = None,
|
|
133
|
+
) -> list[EvictionAction]:
|
|
134
|
+
"""
|
|
135
|
+
Get the eviction actions to evict objects from L1 cache.
|
|
136
|
+
Returns keys in LRU order (least recently used first).
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
expected_ratio (float): A hint indicating approximately what fraction
|
|
140
|
+
of tracked keys should be evicted. Value should be in range [0.0, 1.0].
|
|
141
|
+
For example, 0.1 means roughly 10% of keys should be evicted.
|
|
142
|
+
key_eligible_filter: An optional callable that takes an ObjectKey
|
|
143
|
+
and returns True if the key is eligible for eviction. When
|
|
144
|
+
provided, keys for which the filter returns False will be
|
|
145
|
+
skipped. This is useful for skipping locked keys that
|
|
146
|
+
cannot be deleted.
|
|
147
|
+
cache_salt: Ignored by LRU policy (not user-level).
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
list[EvictionAction]: The eviction actions to perform. Each
|
|
151
|
+
action contains the keys and one eviction destination.
|
|
152
|
+
|
|
153
|
+
Notes:
|
|
154
|
+
The eviction action may not be successfully executed, or it
|
|
155
|
+
may be executed asynchronously. Therefore, the eviction policy
|
|
156
|
+
should not assume that the objects are evicted immediately, but
|
|
157
|
+
it should use `on_keys_deleted` to know when the objects are actually
|
|
158
|
+
deleted.
|
|
159
|
+
"""
|
|
160
|
+
with self._lock:
|
|
161
|
+
if not self._order:
|
|
162
|
+
return []
|
|
163
|
+
|
|
164
|
+
# Clamp expected_ratio to valid range
|
|
165
|
+
expected_ratio = max(0.0, min(1.0, expected_ratio))
|
|
166
|
+
|
|
167
|
+
# Calculate target number of keys to evict based on ratio
|
|
168
|
+
target_count = int(len(self._order) * expected_ratio)
|
|
169
|
+
|
|
170
|
+
# Ensure at least 1 key if ratio > 0 and we have keys
|
|
171
|
+
if expected_ratio > 0 and target_count == 0 and len(self._order) > 0:
|
|
172
|
+
target_count = 1
|
|
173
|
+
|
|
174
|
+
if target_count == 0:
|
|
175
|
+
return []
|
|
176
|
+
|
|
177
|
+
# Get keys in LRU order (from beginning - least recently used),
|
|
178
|
+
# skipping keys that fail the filter (e.g. locked keys).
|
|
179
|
+
keys_to_evict: list[ObjectKey] = []
|
|
180
|
+
|
|
181
|
+
for key in self._order:
|
|
182
|
+
if key_eligible_filter is not None and not key_eligible_filter(key):
|
|
183
|
+
# Skip keys that are not eligible for eviction
|
|
184
|
+
# (e.g. currently locked by read/write operations)
|
|
185
|
+
continue
|
|
186
|
+
keys_to_evict.append(key)
|
|
187
|
+
if len(keys_to_evict) >= target_count:
|
|
188
|
+
break
|
|
189
|
+
|
|
190
|
+
if not keys_to_evict:
|
|
191
|
+
return []
|
|
192
|
+
|
|
193
|
+
# Determine the destination
|
|
194
|
+
destination = self._default_destination
|
|
195
|
+
if self._destinations:
|
|
196
|
+
# Use the first registered destination if available
|
|
197
|
+
destination = self._destinations[0]
|
|
198
|
+
|
|
199
|
+
return [EvictionAction(keys=keys_to_evict, destination=destination)]
|
|
200
|
+
|
|
201
|
+
# =========================================================================
|
|
202
|
+
# Methods below are NOT part of the EvictionPolicy interface.
|
|
203
|
+
# They are provided for testing and debugging purposes only.
|
|
204
|
+
# =========================================================================
|
|
205
|
+
|
|
206
|
+
def get_num_tracked_keys(self) -> int:
|
|
207
|
+
"""
|
|
208
|
+
Get the number of keys currently being tracked.
|
|
209
|
+
|
|
210
|
+
Note:
|
|
211
|
+
This method is NOT part of the EvictionPolicy interface.
|
|
212
|
+
It is provided for testing and debugging purposes only.
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
int: The number of tracked keys
|
|
216
|
+
"""
|
|
217
|
+
with self._lock:
|
|
218
|
+
return len(self._order)
|
|
219
|
+
|
|
220
|
+
def get_eviction_candidates(self, count: int) -> list[ObjectKey]:
|
|
221
|
+
"""
|
|
222
|
+
Get a list of eviction candidates without creating eviction actions.
|
|
223
|
+
Useful for querying what would be evicted.
|
|
224
|
+
|
|
225
|
+
Note:
|
|
226
|
+
This method is NOT part of the EvictionPolicy interface.
|
|
227
|
+
It is provided for testing and debugging purposes only.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
count: Maximum number of candidates to return
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
list[ObjectKey]: List of keys that are candidates for eviction,
|
|
234
|
+
in LRU order (least recently used first)
|
|
235
|
+
"""
|
|
236
|
+
with self._lock:
|
|
237
|
+
candidates: list[ObjectKey] = []
|
|
238
|
+
|
|
239
|
+
for key in self._order:
|
|
240
|
+
candidates.append(key)
|
|
241
|
+
if len(candidates) >= count:
|
|
242
|
+
break
|
|
243
|
+
|
|
244
|
+
return candidates
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
No-op eviction policy for buffer-only mode.
|
|
4
|
+
|
|
5
|
+
When L1 is used purely as a write buffer (data is deleted from L1
|
|
6
|
+
immediately after being stored to L2 by the StoreController), there
|
|
7
|
+
is no need for the eviction policy to track keys at all.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Standard
|
|
11
|
+
from collections.abc import Callable
|
|
12
|
+
|
|
13
|
+
# First Party
|
|
14
|
+
from lmcache.v1.distributed.api import ObjectKey
|
|
15
|
+
from lmcache.v1.distributed.eviction import EvictionPolicy
|
|
16
|
+
from lmcache.v1.distributed.internal_api import (
|
|
17
|
+
EvictionAction,
|
|
18
|
+
EvictionDestination,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class NoOpEvictionPolicy(EvictionPolicy):
|
|
23
|
+
"""
|
|
24
|
+
Eviction policy that performs no tracking and never evicts.
|
|
25
|
+
|
|
26
|
+
Designed for buffer-only mode where the StoreController is
|
|
27
|
+
responsible for cleaning up L1 after successful L2 writes.
|
|
28
|
+
This avoids the overhead of maintaining an LRU OrderedDict
|
|
29
|
+
that would otherwise do pointless insert-then-remove cycles.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def register_eviction_destination(self, destination: EvictionDestination):
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
def on_keys_created(self, keys: list[ObjectKey]):
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
def on_keys_touched(self, keys: list[ObjectKey]):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
def on_keys_removed(self, keys: list[ObjectKey]):
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
def get_eviction_actions(
|
|
45
|
+
self,
|
|
46
|
+
expected_ratio: float,
|
|
47
|
+
key_eligible_filter: Callable[[ObjectKey], bool] | None = None,
|
|
48
|
+
cache_salt: str | None = None,
|
|
49
|
+
) -> list[EvictionAction]:
|
|
50
|
+
return []
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
Class for distributed storage manager internal API data structures
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
# Standard
|
|
7
|
+
from abc import ABC, abstractmethod
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
import enum
|
|
10
|
+
|
|
11
|
+
# First Party
|
|
12
|
+
from lmcache.v1.distributed.api import ObjectKey
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class L1MemoryDesc:
|
|
17
|
+
"""
|
|
18
|
+
Describes the L1 memory buffer registered with an external backend (e.g. Nixl).
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
ptr: int
|
|
22
|
+
size: int
|
|
23
|
+
align_bytes: int
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class EventListener(ABC): # noqa: B024
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# For L1 manager event notifications
|
|
31
|
+
class L1ManagerListener(EventListener):
|
|
32
|
+
"""
|
|
33
|
+
Listener for L1 manager events
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def on_l1_keys_reserved_read(self, keys: list[ObjectKey]):
|
|
38
|
+
"""
|
|
39
|
+
Notify the listener that new keys have been reserved for read on L1.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
keys (list[ObjectKey]): The keys that have been successfully reserved
|
|
43
|
+
"""
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def on_l1_keys_read_finished(self, keys: list[ObjectKey]):
|
|
48
|
+
"""
|
|
49
|
+
Notify the listener that keys have been accessed on L1.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
keys (list[ObjectKey]): The keys that have been successfully read
|
|
53
|
+
"""
|
|
54
|
+
pass
|
|
55
|
+
|
|
56
|
+
@abstractmethod
|
|
57
|
+
def on_l1_keys_reserved_write(self, keys: list[ObjectKey]):
|
|
58
|
+
"""
|
|
59
|
+
Notify the listener that keys have been reserved for write on L1.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
keys (list[ObjectKey]): The keys that have been successfully reserved
|
|
63
|
+
"""
|
|
64
|
+
pass
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def on_l1_keys_write_finished(self, keys: list[ObjectKey]):
|
|
68
|
+
"""
|
|
69
|
+
Notify the listener that keys have been finished for writing on L1.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
keys (list[ObjectKey]): The keys that have been successfully written
|
|
73
|
+
"""
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
@abstractmethod
|
|
77
|
+
def on_l1_keys_finish_write_and_reserve_read(self, keys: list[ObjectKey]):
|
|
78
|
+
"""
|
|
79
|
+
Notify the listener that keys have been finished for writing
|
|
80
|
+
and reserved for read on L1.
|
|
81
|
+
|
|
82
|
+
This will only be trigger by the prefetch operation now.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
keys (list[ObjectKey]): The keys that have been successfully
|
|
86
|
+
finished for writing and reserved for read
|
|
87
|
+
"""
|
|
88
|
+
# NOTE (ApostaC): may consider renaming this to `on_l1_keys_finish_prefetch`
|
|
89
|
+
# for better clarity
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
@abstractmethod
|
|
93
|
+
def on_l1_keys_deleted_by_manager(self, keys: list[ObjectKey]):
|
|
94
|
+
"""
|
|
95
|
+
Notify the listener that keys have been deleted from L1.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
keys (list[ObjectKey]): The keys that have been deleted
|
|
99
|
+
"""
|
|
100
|
+
pass
|
|
101
|
+
|
|
102
|
+
@abstractmethod
|
|
103
|
+
def on_l1_keys_accessed(self, keys: list[ObjectKey]):
|
|
104
|
+
"""
|
|
105
|
+
Notify the listener that keys have been accessed on L1.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
keys (list[ObjectKey]): The keys that have been accessed
|
|
109
|
+
"""
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class L2AdapterListener(EventListener):
|
|
114
|
+
"""Listener for L2 adapter events, analogous to L1ManagerListener."""
|
|
115
|
+
|
|
116
|
+
@abstractmethod
|
|
117
|
+
def on_l2_keys_stored(self, keys: list[ObjectKey]):
|
|
118
|
+
"""
|
|
119
|
+
Notify the listener that keys have been successfully stored in L2.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
keys (list[ObjectKey]): The keys that have been stored.
|
|
123
|
+
"""
|
|
124
|
+
pass
|
|
125
|
+
|
|
126
|
+
@abstractmethod
|
|
127
|
+
def on_l2_keys_accessed(self, keys: list[ObjectKey]):
|
|
128
|
+
"""
|
|
129
|
+
Notify the listener that keys have been accessed (lookup hit) in L2.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
keys (list[ObjectKey]): The keys that have been accessed.
|
|
133
|
+
"""
|
|
134
|
+
pass
|
|
135
|
+
|
|
136
|
+
@abstractmethod
|
|
137
|
+
def on_l2_keys_deleted(self, keys: list[ObjectKey]):
|
|
138
|
+
"""
|
|
139
|
+
Notify the listener that keys have been deleted from L2.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
keys (list[ObjectKey]): The keys that have been deleted.
|
|
143
|
+
"""
|
|
144
|
+
pass
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
# For Eviction
|
|
148
|
+
class EvictionDestination(enum.Enum):
|
|
149
|
+
"""
|
|
150
|
+
The destination of evicted objects
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
DISCARD = enum.auto()
|
|
154
|
+
"""Discard the evicted objects"""
|
|
155
|
+
|
|
156
|
+
L2_CACHE = enum.auto()
|
|
157
|
+
"""Evict to L2 storage"""
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@dataclass(frozen=True)
|
|
161
|
+
class EvictionAction:
|
|
162
|
+
"""
|
|
163
|
+
An action to be taken for eviction
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
destination: EvictionDestination
|
|
167
|
+
"""The destination of the evicted object"""
|
|
168
|
+
|
|
169
|
+
keys: list[ObjectKey] = field(default_factory=list)
|
|
170
|
+
"""The key of the object to be evicted"""
|