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.
Files changed (399) hide show
  1. lmcache/__init__.py +84 -0
  2. lmcache/_version.py +24 -0
  3. lmcache/cli/__init__.py +1 -0
  4. lmcache/cli/commands/__init__.py +34 -0
  5. lmcache/cli/commands/base.py +157 -0
  6. lmcache/cli/commands/bench/__init__.py +557 -0
  7. lmcache/cli/commands/bench/engine_bench/__init__.py +1 -0
  8. lmcache/cli/commands/bench/engine_bench/config.py +245 -0
  9. lmcache/cli/commands/bench/engine_bench/interactive/__init__.py +274 -0
  10. lmcache/cli/commands/bench/engine_bench/interactive/config.json +10 -0
  11. lmcache/cli/commands/bench/engine_bench/interactive/schema.py +352 -0
  12. lmcache/cli/commands/bench/engine_bench/interactive/state.py +327 -0
  13. lmcache/cli/commands/bench/engine_bench/interactive/terminal.py +291 -0
  14. lmcache/cli/commands/bench/engine_bench/progress.py +145 -0
  15. lmcache/cli/commands/bench/engine_bench/request_sender.py +232 -0
  16. lmcache/cli/commands/bench/engine_bench/stats.py +275 -0
  17. lmcache/cli/commands/bench/engine_bench/workloads/__init__.py +153 -0
  18. lmcache/cli/commands/bench/engine_bench/workloads/base.py +122 -0
  19. lmcache/cli/commands/bench/engine_bench/workloads/long_doc_permutator.py +435 -0
  20. lmcache/cli/commands/bench/engine_bench/workloads/long_doc_qa.py +281 -0
  21. lmcache/cli/commands/bench/engine_bench/workloads/multi_round_chat.py +337 -0
  22. lmcache/cli/commands/bench/engine_bench/workloads/random_prefill.py +178 -0
  23. lmcache/cli/commands/describe.py +310 -0
  24. lmcache/cli/commands/kvcache.py +133 -0
  25. lmcache/cli/commands/mock.py +75 -0
  26. lmcache/cli/commands/ping.py +113 -0
  27. lmcache/cli/commands/query/__init__.py +155 -0
  28. lmcache/cli/commands/query/prompt.py +134 -0
  29. lmcache/cli/commands/query/request.py +357 -0
  30. lmcache/cli/commands/server.py +99 -0
  31. lmcache/cli/commands/tool/__init__.py +63 -0
  32. lmcache/cli/commands/tool/cache_simulator.py +113 -0
  33. lmcache/cli/commands/trace/__init__.py +505 -0
  34. lmcache/cli/commands/trace/dispatch.py +249 -0
  35. lmcache/cli/commands/trace/driver.py +372 -0
  36. lmcache/cli/commands/trace/stats.py +289 -0
  37. lmcache/cli/documents/lmcache.txt +11 -0
  38. lmcache/cli/main.py +42 -0
  39. lmcache/cli/metrics/__init__.py +29 -0
  40. lmcache/cli/metrics/formatter.py +171 -0
  41. lmcache/cli/metrics/handler.py +94 -0
  42. lmcache/cli/metrics/metrics.py +161 -0
  43. lmcache/cli/metrics/section.py +77 -0
  44. lmcache/connections.py +173 -0
  45. lmcache/integration/__init__.py +2 -0
  46. lmcache/integration/base_service_factory.py +165 -0
  47. lmcache/integration/request_telemetry/__init__.py +1 -0
  48. lmcache/integration/request_telemetry/base.py +51 -0
  49. lmcache/integration/request_telemetry/factory.py +113 -0
  50. lmcache/integration/request_telemetry/fastapi.py +109 -0
  51. lmcache/integration/request_telemetry/noop.py +35 -0
  52. lmcache/integration/sglang/__init__.py +2 -0
  53. lmcache/integration/sglang/sglang_adapter.py +326 -0
  54. lmcache/integration/sglang/utils.py +39 -0
  55. lmcache/integration/vllm/__init__.py +1 -0
  56. lmcache/integration/vllm/lmcache_connector_v1.py +213 -0
  57. lmcache/integration/vllm/lmcache_connector_v1_085.py +150 -0
  58. lmcache/integration/vllm/lmcache_mp_connector_0180.py +1072 -0
  59. lmcache/integration/vllm/tests/test_mm_hash_utils.py +112 -0
  60. lmcache/integration/vllm/utils.py +433 -0
  61. lmcache/integration/vllm/vllm_multi_process_adapter.py +1090 -0
  62. lmcache/integration/vllm/vllm_service_factory.py +339 -0
  63. lmcache/integration/vllm/vllm_v1_adapter.py +1713 -0
  64. lmcache/logging.py +107 -0
  65. lmcache/native_storage_ops.pyi +230 -0
  66. lmcache/non_cuda_equivalents.py +1424 -0
  67. lmcache/observability.py +1958 -0
  68. lmcache/storage_backend/serde/__init__.py +1 -0
  69. lmcache/storage_backend/serde/cachegen_basics.py +210 -0
  70. lmcache/storage_backend/serde/cachegen_decoder.py +207 -0
  71. lmcache/storage_backend/serde/cachegen_encoder.py +394 -0
  72. lmcache/storage_backend/serde/serde.py +75 -0
  73. lmcache/tools/__init__.py +1 -0
  74. lmcache/tools/cache_simulator/README.md +392 -0
  75. lmcache/tools/cache_simulator/__init__.py +1 -0
  76. lmcache/tools/cache_simulator/docs/simulate_example.png +0 -0
  77. lmcache/tools/cache_simulator/docs/sweep_example.png +0 -0
  78. lmcache/tools/cache_simulator/gen_bench_dataset.py +360 -0
  79. lmcache/tools/cache_simulator/lru_cache.py +124 -0
  80. lmcache/tools/cache_simulator/plot_hit_rate.py +231 -0
  81. lmcache/tools/cache_simulator/simulator.py +795 -0
  82. lmcache/tools/controller_benchmark/README.md +161 -0
  83. lmcache/tools/controller_benchmark/__init__.py +1 -0
  84. lmcache/tools/controller_benchmark/__main__.py +331 -0
  85. lmcache/tools/controller_benchmark/benchmark.py +660 -0
  86. lmcache/tools/controller_benchmark/config.py +44 -0
  87. lmcache/tools/controller_benchmark/constants.py +10 -0
  88. lmcache/tools/controller_benchmark/handlers/__init__.py +46 -0
  89. lmcache/tools/controller_benchmark/handlers/admit.py +52 -0
  90. lmcache/tools/controller_benchmark/handlers/base.py +47 -0
  91. lmcache/tools/controller_benchmark/handlers/deregister.py +49 -0
  92. lmcache/tools/controller_benchmark/handlers/evict.py +52 -0
  93. lmcache/tools/controller_benchmark/handlers/heartbeat.py +56 -0
  94. lmcache/tools/controller_benchmark/handlers/p2p_lookup.py +47 -0
  95. lmcache/tools/controller_benchmark/handlers/register.py +56 -0
  96. lmcache/tools/mp_status_viewer/__init__.py +1 -0
  97. lmcache/tools/mp_status_viewer/__main__.py +95 -0
  98. lmcache/usage_context.py +417 -0
  99. lmcache/utils.py +665 -0
  100. lmcache/v1/__init__.py +2 -0
  101. lmcache/v1/api_server/__init__.py +2 -0
  102. lmcache/v1/api_server/__main__.py +537 -0
  103. lmcache/v1/basic_check.py +112 -0
  104. lmcache/v1/cache_controller/__init__.py +9 -0
  105. lmcache/v1/cache_controller/commands/__init__.py +15 -0
  106. lmcache/v1/cache_controller/commands/base.py +35 -0
  107. lmcache/v1/cache_controller/commands/full_sync.py +49 -0
  108. lmcache/v1/cache_controller/config.py +176 -0
  109. lmcache/v1/cache_controller/controller_manager.py +535 -0
  110. lmcache/v1/cache_controller/controllers/__init__.py +11 -0
  111. lmcache/v1/cache_controller/controllers/full_sync_tracker.py +473 -0
  112. lmcache/v1/cache_controller/controllers/kv_controller.py +439 -0
  113. lmcache/v1/cache_controller/controllers/registration_controller.py +282 -0
  114. lmcache/v1/cache_controller/executor.py +463 -0
  115. lmcache/v1/cache_controller/frontend/static/css/style.css +201 -0
  116. lmcache/v1/cache_controller/frontend/static/img/logo.png +0 -0
  117. lmcache/v1/cache_controller/frontend/static/index.html +234 -0
  118. lmcache/v1/cache_controller/frontend/static/js/controller_app.js +660 -0
  119. lmcache/v1/cache_controller/full_sync_sender.py +475 -0
  120. lmcache/v1/cache_controller/locks.py +149 -0
  121. lmcache/v1/cache_controller/message.py +828 -0
  122. lmcache/v1/cache_controller/observability.py +208 -0
  123. lmcache/v1/cache_controller/utils.py +679 -0
  124. lmcache/v1/cache_controller/worker.py +665 -0
  125. lmcache/v1/cache_engine.py +2058 -0
  126. lmcache/v1/cache_interface.py +19 -0
  127. lmcache/v1/check/__init__.py +74 -0
  128. lmcache/v1/check/check_mode_gen.py +86 -0
  129. lmcache/v1/check/check_mode_test_l2_adapter.py +284 -0
  130. lmcache/v1/check/check_mode_test_remote.py +155 -0
  131. lmcache/v1/check/check_mode_test_storage_manager.py +142 -0
  132. lmcache/v1/check/utils.py +571 -0
  133. lmcache/v1/compute/__init__.py +2 -0
  134. lmcache/v1/compute/attention/__init__.py +0 -0
  135. lmcache/v1/compute/attention/abstract.py +39 -0
  136. lmcache/v1/compute/attention/flash_attn.py +129 -0
  137. lmcache/v1/compute/attention/flash_infer_sparse.py +284 -0
  138. lmcache/v1/compute/attention/metadata.py +85 -0
  139. lmcache/v1/compute/attention/utils.py +14 -0
  140. lmcache/v1/compute/blend/__init__.py +7 -0
  141. lmcache/v1/compute/blend/blender.py +168 -0
  142. lmcache/v1/compute/blend/metadata.py +34 -0
  143. lmcache/v1/compute/blend/utils.py +63 -0
  144. lmcache/v1/compute/models/__init__.py +0 -0
  145. lmcache/v1/compute/models/base.py +141 -0
  146. lmcache/v1/compute/models/llama.py +9 -0
  147. lmcache/v1/compute/models/qwen3.py +24 -0
  148. lmcache/v1/compute/models/utils.py +68 -0
  149. lmcache/v1/compute/positional_encoding.py +199 -0
  150. lmcache/v1/config.py +848 -0
  151. lmcache/v1/config_base.py +848 -0
  152. lmcache/v1/distributed/api.py +248 -0
  153. lmcache/v1/distributed/config.py +321 -0
  154. lmcache/v1/distributed/error.py +64 -0
  155. lmcache/v1/distributed/eviction.py +192 -0
  156. lmcache/v1/distributed/eviction_policy/__init__.py +21 -0
  157. lmcache/v1/distributed/eviction_policy/factory.py +27 -0
  158. lmcache/v1/distributed/eviction_policy/lru.py +244 -0
  159. lmcache/v1/distributed/eviction_policy/noop.py +50 -0
  160. lmcache/v1/distributed/internal_api.py +170 -0
  161. lmcache/v1/distributed/l1_manager.py +835 -0
  162. lmcache/v1/distributed/l2_adapters/__init__.py +67 -0
  163. lmcache/v1/distributed/l2_adapters/base.py +360 -0
  164. lmcache/v1/distributed/l2_adapters/config.py +385 -0
  165. lmcache/v1/distributed/l2_adapters/factory.py +205 -0
  166. lmcache/v1/distributed/l2_adapters/fs_l2_adapter.py +747 -0
  167. lmcache/v1/distributed/l2_adapters/fs_native_l2_adapter.py +167 -0
  168. lmcache/v1/distributed/l2_adapters/mock_l2_adapter.py +516 -0
  169. lmcache/v1/distributed/l2_adapters/mooncake_store_l2_adapter.py +135 -0
  170. lmcache/v1/distributed/l2_adapters/native_connector_l2_adapter.py +468 -0
  171. lmcache/v1/distributed/l2_adapters/native_plugin_l2_adapter.py +199 -0
  172. lmcache/v1/distributed/l2_adapters/nixl_store_dynamic_l2_adapter.py +831 -0
  173. lmcache/v1/distributed/l2_adapters/nixl_store_l2_adapter.py +983 -0
  174. lmcache/v1/distributed/l2_adapters/plugin_l2_adapter.py +210 -0
  175. lmcache/v1/distributed/l2_adapters/resp_l2_adapter.py +176 -0
  176. lmcache/v1/distributed/memory_manager.py +179 -0
  177. lmcache/v1/distributed/storage_controller.py +39 -0
  178. lmcache/v1/distributed/storage_controllers/__init__.py +43 -0
  179. lmcache/v1/distributed/storage_controllers/eviction_controller.py +242 -0
  180. lmcache/v1/distributed/storage_controllers/prefetch_controller.py +830 -0
  181. lmcache/v1/distributed/storage_controllers/prefetch_policy.py +193 -0
  182. lmcache/v1/distributed/storage_controllers/store_controller.py +452 -0
  183. lmcache/v1/distributed/storage_controllers/store_policy.py +213 -0
  184. lmcache/v1/distributed/storage_manager.py +532 -0
  185. lmcache/v1/event_manager.py +145 -0
  186. lmcache/v1/exceptions/__init__.py +16 -0
  187. lmcache/v1/gpu_connector/__init__.py +126 -0
  188. lmcache/v1/gpu_connector/gpu_connectors.py +1906 -0
  189. lmcache/v1/gpu_connector/gpu_ops.py +85 -0
  190. lmcache/v1/gpu_connector/hpu_connector.py +326 -0
  191. lmcache/v1/gpu_connector/mock_gpu_connector.py +67 -0
  192. lmcache/v1/gpu_connector/utils.py +890 -0
  193. lmcache/v1/gpu_connector/xpu_connectors.py +916 -0
  194. lmcache/v1/health_monitor/__init__.py +1 -0
  195. lmcache/v1/health_monitor/base.py +587 -0
  196. lmcache/v1/health_monitor/checks/__init__.py +1 -0
  197. lmcache/v1/health_monitor/checks/remote_backend_check.py +304 -0
  198. lmcache/v1/health_monitor/constants.py +36 -0
  199. lmcache/v1/internal_api_server/__init__.py +0 -0
  200. lmcache/v1/internal_api_server/api_registry.py +59 -0
  201. lmcache/v1/internal_api_server/api_server.py +120 -0
  202. lmcache/v1/internal_api_server/common/__init__.py +1 -0
  203. lmcache/v1/internal_api_server/common/env_api.py +22 -0
  204. lmcache/v1/internal_api_server/common/loglevel_api.py +57 -0
  205. lmcache/v1/internal_api_server/common/metrics_api.py +29 -0
  206. lmcache/v1/internal_api_server/common/periodic_thread_api.py +138 -0
  207. lmcache/v1/internal_api_server/common/run_script_api.py +73 -0
  208. lmcache/v1/internal_api_server/common/thread_api.py +63 -0
  209. lmcache/v1/internal_api_server/controller/__init__.py +1 -0
  210. lmcache/v1/internal_api_server/controller/key_stats_api.py +81 -0
  211. lmcache/v1/internal_api_server/controller/worker_info_api.py +136 -0
  212. lmcache/v1/internal_api_server/utils.py +43 -0
  213. lmcache/v1/internal_api_server/vllm/__init__.py +1 -0
  214. lmcache/v1/internal_api_server/vllm/backend_api.py +221 -0
  215. lmcache/v1/internal_api_server/vllm/bypass_api.py +204 -0
  216. lmcache/v1/internal_api_server/vllm/cache_api.py +895 -0
  217. lmcache/v1/internal_api_server/vllm/chunk_statistics_api.py +141 -0
  218. lmcache/v1/internal_api_server/vllm/conf_api.py +147 -0
  219. lmcache/v1/internal_api_server/vllm/freeze_api.py +172 -0
  220. lmcache/v1/internal_api_server/vllm/hot_cache_api.py +184 -0
  221. lmcache/v1/internal_api_server/vllm/inference_api.py +65 -0
  222. lmcache/v1/internal_api_server/vllm/load_fs_chunks_api.py +320 -0
  223. lmcache/v1/internal_api_server/vllm/lookup_api.py +145 -0
  224. lmcache/v1/internal_api_server/vllm/version_api.py +25 -0
  225. lmcache/v1/kv_layer_groups.py +267 -0
  226. lmcache/v1/lazy_memory_allocator.py +284 -0
  227. lmcache/v1/lookup_client/__init__.py +25 -0
  228. lmcache/v1/lookup_client/abstract_client.py +77 -0
  229. lmcache/v1/lookup_client/async_lookup_message.py +50 -0
  230. lmcache/v1/lookup_client/chunk_statistics_lookup_client.py +200 -0
  231. lmcache/v1/lookup_client/factory.py +251 -0
  232. lmcache/v1/lookup_client/hit_limit_lookup_client.py +86 -0
  233. lmcache/v1/lookup_client/lmcache_async_lookup_client.py +407 -0
  234. lmcache/v1/lookup_client/lmcache_lookup_client.py +285 -0
  235. lmcache/v1/lookup_client/lmcache_lookup_client_bypass.py +99 -0
  236. lmcache/v1/lookup_client/mooncake_lookup_client.py +87 -0
  237. lmcache/v1/lookup_client/record_strategies/__init__.py +77 -0
  238. lmcache/v1/lookup_client/record_strategies/base.py +327 -0
  239. lmcache/v1/lookup_client/record_strategies/file_hash.py +130 -0
  240. lmcache/v1/lookup_client/record_strategies/memory_bloom_filter.py +81 -0
  241. lmcache/v1/manager.py +539 -0
  242. lmcache/v1/memory_management.py +2619 -0
  243. lmcache/v1/metadata.py +114 -0
  244. lmcache/v1/mp_observability/AGENTS.override.md +21 -0
  245. lmcache/v1/mp_observability/README.md +204 -0
  246. lmcache/v1/mp_observability/config.py +340 -0
  247. lmcache/v1/mp_observability/event.py +100 -0
  248. lmcache/v1/mp_observability/event_bus.py +313 -0
  249. lmcache/v1/mp_observability/otel_init.py +145 -0
  250. lmcache/v1/mp_observability/subscribers/__init__.py +28 -0
  251. lmcache/v1/mp_observability/subscribers/logging/__init__.py +19 -0
  252. lmcache/v1/mp_observability/subscribers/logging/l1.py +56 -0
  253. lmcache/v1/mp_observability/subscribers/logging/l2.py +73 -0
  254. lmcache/v1/mp_observability/subscribers/logging/lookup_hash.py +209 -0
  255. lmcache/v1/mp_observability/subscribers/logging/mp_server.py +90 -0
  256. lmcache/v1/mp_observability/subscribers/logging/sm.py +59 -0
  257. lmcache/v1/mp_observability/subscribers/metrics/__init__.py +20 -0
  258. lmcache/v1/mp_observability/subscribers/metrics/l0_lifecycle.py +290 -0
  259. lmcache/v1/mp_observability/subscribers/metrics/l1.py +55 -0
  260. lmcache/v1/mp_observability/subscribers/metrics/l1_lifecycle.py +166 -0
  261. lmcache/v1/mp_observability/subscribers/metrics/l2.py +121 -0
  262. lmcache/v1/mp_observability/subscribers/metrics/sm.py +69 -0
  263. lmcache/v1/mp_observability/subscribers/tracing/__init__.py +12 -0
  264. lmcache/v1/mp_observability/subscribers/tracing/mp_server.py +333 -0
  265. lmcache/v1/mp_observability/subscribers/tracing/span_registry.py +148 -0
  266. lmcache/v1/mp_observability/trace/__init__.py +50 -0
  267. lmcache/v1/mp_observability/trace/codecs.py +255 -0
  268. lmcache/v1/mp_observability/trace/decorator.py +147 -0
  269. lmcache/v1/mp_observability/trace/format.py +132 -0
  270. lmcache/v1/mp_observability/trace/lifecycle.py +83 -0
  271. lmcache/v1/mp_observability/trace/reader.py +167 -0
  272. lmcache/v1/mp_observability/trace/recorder.py +300 -0
  273. lmcache/v1/multiprocess/__init__.py +0 -0
  274. lmcache/v1/multiprocess/affinity_pool.py +102 -0
  275. lmcache/v1/multiprocess/blend_server_v2.py +891 -0
  276. lmcache/v1/multiprocess/config.py +253 -0
  277. lmcache/v1/multiprocess/custom_types.py +281 -0
  278. lmcache/v1/multiprocess/futures.py +194 -0
  279. lmcache/v1/multiprocess/gpu_context.py +511 -0
  280. lmcache/v1/multiprocess/http_server.py +235 -0
  281. lmcache/v1/multiprocess/mp_runtime_plugin_launcher.py +130 -0
  282. lmcache/v1/multiprocess/mq.py +732 -0
  283. lmcache/v1/multiprocess/protocol.py +86 -0
  284. lmcache/v1/multiprocess/protocols/README.md +213 -0
  285. lmcache/v1/multiprocess/protocols/__init__.py +127 -0
  286. lmcache/v1/multiprocess/protocols/base.py +89 -0
  287. lmcache/v1/multiprocess/protocols/blend.py +109 -0
  288. lmcache/v1/multiprocess/protocols/blend_v2.py +57 -0
  289. lmcache/v1/multiprocess/protocols/controller.py +53 -0
  290. lmcache/v1/multiprocess/protocols/debug.py +34 -0
  291. lmcache/v1/multiprocess/protocols/engine.py +146 -0
  292. lmcache/v1/multiprocess/protocols/observability.py +39 -0
  293. lmcache/v1/multiprocess/server.py +1134 -0
  294. lmcache/v1/multiprocess/session.py +190 -0
  295. lmcache/v1/multiprocess/token_hasher.py +441 -0
  296. lmcache/v1/offload_server/__init__.py +17 -0
  297. lmcache/v1/offload_server/abstract_server.py +37 -0
  298. lmcache/v1/offload_server/message.py +30 -0
  299. lmcache/v1/offload_server/zmq_server.py +122 -0
  300. lmcache/v1/periodic_thread.py +579 -0
  301. lmcache/v1/pin_monitor.py +246 -0
  302. lmcache/v1/plugin/__init__.py +0 -0
  303. lmcache/v1/plugin/runtime_plugin_launcher.py +211 -0
  304. lmcache/v1/protocol.py +317 -0
  305. lmcache/v1/rpc/__init__.py +17 -0
  306. lmcache/v1/rpc/transport.py +105 -0
  307. lmcache/v1/rpc/zmq_transport.py +213 -0
  308. lmcache/v1/rpc_utils.py +165 -0
  309. lmcache/v1/server/__init__.py +2 -0
  310. lmcache/v1/server/__main__.py +170 -0
  311. lmcache/v1/server/storage_backend/__init__.py +21 -0
  312. lmcache/v1/server/storage_backend/abstract_backend.py +80 -0
  313. lmcache/v1/server/storage_backend/local_backend.py +75 -0
  314. lmcache/v1/server/utils.py +21 -0
  315. lmcache/v1/standalone/__init__.py +1 -0
  316. lmcache/v1/standalone/__main__.py +583 -0
  317. lmcache/v1/standalone/manager.py +80 -0
  318. lmcache/v1/standalone/standalone_service_factory.py +86 -0
  319. lmcache/v1/storage_backend/__init__.py +313 -0
  320. lmcache/v1/storage_backend/abstract_backend.py +445 -0
  321. lmcache/v1/storage_backend/audit_backend.py +233 -0
  322. lmcache/v1/storage_backend/batched_message_sender.py +222 -0
  323. lmcache/v1/storage_backend/cache_policy/__init__.py +45 -0
  324. lmcache/v1/storage_backend/cache_policy/base_policy.py +87 -0
  325. lmcache/v1/storage_backend/cache_policy/fifo.py +58 -0
  326. lmcache/v1/storage_backend/cache_policy/lfu.py +105 -0
  327. lmcache/v1/storage_backend/cache_policy/lru.py +81 -0
  328. lmcache/v1/storage_backend/cache_policy/mru.py +61 -0
  329. lmcache/v1/storage_backend/connector/__init__.py +443 -0
  330. lmcache/v1/storage_backend/connector/audit_adapter.py +77 -0
  331. lmcache/v1/storage_backend/connector/audit_connector.py +320 -0
  332. lmcache/v1/storage_backend/connector/base_connector.py +379 -0
  333. lmcache/v1/storage_backend/connector/blackhole_adapter.py +21 -0
  334. lmcache/v1/storage_backend/connector/blackhole_connector.py +37 -0
  335. lmcache/v1/storage_backend/connector/eic_adapter.py +31 -0
  336. lmcache/v1/storage_backend/connector/eic_connector.py +757 -0
  337. lmcache/v1/storage_backend/connector/external_adapter.py +79 -0
  338. lmcache/v1/storage_backend/connector/fs_adapter.py +51 -0
  339. lmcache/v1/storage_backend/connector/fs_connector.py +403 -0
  340. lmcache/v1/storage_backend/connector/infinistore_adapter.py +56 -0
  341. lmcache/v1/storage_backend/connector/infinistore_connector.py +177 -0
  342. lmcache/v1/storage_backend/connector/instrumented_connector.py +219 -0
  343. lmcache/v1/storage_backend/connector/lm_adapter.py +31 -0
  344. lmcache/v1/storage_backend/connector/lm_connector.py +176 -0
  345. lmcache/v1/storage_backend/connector/mock_adapter.py +57 -0
  346. lmcache/v1/storage_backend/connector/mock_connector.py +349 -0
  347. lmcache/v1/storage_backend/connector/mooncakestore_adapter.py +43 -0
  348. lmcache/v1/storage_backend/connector/mooncakestore_connector.py +614 -0
  349. lmcache/v1/storage_backend/connector/redis_adapter.py +181 -0
  350. lmcache/v1/storage_backend/connector/redis_connector.py +828 -0
  351. lmcache/v1/storage_backend/connector/s3_adapter.py +59 -0
  352. lmcache/v1/storage_backend/connector/s3_connector.py +699 -0
  353. lmcache/v1/storage_backend/connector/sagemaker_hyperpod_adapter.py +233 -0
  354. lmcache/v1/storage_backend/connector/sagemaker_hyperpod_connector.py +987 -0
  355. lmcache/v1/storage_backend/connector/valkey_adapter.py +114 -0
  356. lmcache/v1/storage_backend/connector/valkey_connector.py +627 -0
  357. lmcache/v1/storage_backend/gds_backend.py +1199 -0
  358. lmcache/v1/storage_backend/job_executor/__init__.py +0 -0
  359. lmcache/v1/storage_backend/job_executor/base_executor.py +34 -0
  360. lmcache/v1/storage_backend/job_executor/pq_executor.py +235 -0
  361. lmcache/v1/storage_backend/local_cpu_backend.py +810 -0
  362. lmcache/v1/storage_backend/local_disk_backend.py +656 -0
  363. lmcache/v1/storage_backend/maru_backend.py +734 -0
  364. lmcache/v1/storage_backend/naive_serde/__init__.py +50 -0
  365. lmcache/v1/storage_backend/naive_serde/cachegen_basics.py +133 -0
  366. lmcache/v1/storage_backend/naive_serde/cachegen_decoder.py +135 -0
  367. lmcache/v1/storage_backend/naive_serde/cachegen_encoder.py +83 -0
  368. lmcache/v1/storage_backend/naive_serde/kivi_serde.py +22 -0
  369. lmcache/v1/storage_backend/naive_serde/naive_serde.py +18 -0
  370. lmcache/v1/storage_backend/naive_serde/serde.py +37 -0
  371. lmcache/v1/storage_backend/native_clients/connector_client_base.py +165 -0
  372. lmcache/v1/storage_backend/native_clients/resp_client.py +35 -0
  373. lmcache/v1/storage_backend/nixl_storage_backend.py +1400 -0
  374. lmcache/v1/storage_backend/p2p_backend.py +788 -0
  375. lmcache/v1/storage_backend/path_sharder.py +117 -0
  376. lmcache/v1/storage_backend/pd_backend.py +646 -0
  377. lmcache/v1/storage_backend/plugins/dax_backend.py +1443 -0
  378. lmcache/v1/storage_backend/plugins/rust_raw_block_backend.py +1361 -0
  379. lmcache/v1/storage_backend/remote_backend.py +624 -0
  380. lmcache/v1/storage_backend/resp_client.py +227 -0
  381. lmcache/v1/storage_backend/storage_backend_listener.py +19 -0
  382. lmcache/v1/storage_backend/storage_manager.py +1352 -0
  383. lmcache/v1/system_detection.py +110 -0
  384. lmcache/v1/token_database.py +551 -0
  385. lmcache/v1/transfer_channel/__init__.py +83 -0
  386. lmcache/v1/transfer_channel/abstract.py +285 -0
  387. lmcache/v1/transfer_channel/mock_memory_channel.py +156 -0
  388. lmcache/v1/transfer_channel/nixl_channel.py +639 -0
  389. lmcache/v1/transfer_channel/py_socket_channel.py +260 -0
  390. lmcache/v1/transfer_channel/transfer_utils.py +63 -0
  391. lmcache/v1/utils/__init__.py +1 -0
  392. lmcache/v1/utils/bloom_filter.py +109 -0
  393. lmcache/v1/utils/cache_utils.py +125 -0
  394. lmcache_cli-0.4.5.dev0.dist-info/METADATA +185 -0
  395. lmcache_cli-0.4.5.dev0.dist-info/RECORD +399 -0
  396. lmcache_cli-0.4.5.dev0.dist-info/WHEEL +5 -0
  397. lmcache_cli-0.4.5.dev0.dist-info/entry_points.txt +2 -0
  398. lmcache_cli-0.4.5.dev0.dist-info/licenses/LICENSE +201 -0
  399. lmcache_cli-0.4.5.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,83 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Standard
3
+ from typing import Optional
4
+
5
+ # First Party
6
+ from lmcache.v1.transfer_channel.abstract import BaseTransferChannel
7
+
8
+
9
+ # TODO(Jiayi): Refactor this function when we support more channels.
10
+ def CreateTransferChannel(
11
+ channel_type: str,
12
+ async_mode: bool,
13
+ role: str,
14
+ buffer_ptr: int,
15
+ buffer_size: int,
16
+ align_bytes: int,
17
+ tp_rank: int,
18
+ peer_init_url: str,
19
+ device: Optional[str] = None,
20
+ **kwargs,
21
+ ) -> BaseTransferChannel:
22
+ """
23
+ Create a transfer channel based on the specified channel type.
24
+ Supports "nixl" and "mock_memory" channel types.
25
+ If nixl is not available, automatically falls back to mock_memory
26
+ which is a mock implementation for testing purposes.
27
+
28
+ :param channel_type: Type of the transfer channel (e.g., "nixl", "mock_memory").
29
+ :param async_mode: Whether to operate in asynchronous mode.
30
+ :param role: Role of the channel (e.g., "both", "sender" or "receiver").
31
+ :param buffer_ptr: Pointer to the pre-allocated buffer.
32
+ :param buffer_size: Size of the pre-allocated buffer in bytes.
33
+ :param align_bytes: Alignment requirement in bytes.
34
+ :param tp_rank: Tensor parallel rank of the current process.
35
+ :param peer_init_url: Initialization URL for the peer.
36
+ :kwargs: Additional keyword arguments specific to the channel type.
37
+
38
+ :return: An instance of the specified transfer channel.
39
+ """
40
+
41
+ assert channel_type in ["nixl", "mock_memory"], (
42
+ f"Unsupported channel type: {channel_type}"
43
+ )
44
+
45
+ if channel_type == "nixl":
46
+ # First Party
47
+ from lmcache.v1.transfer_channel.nixl_channel import NixlChannel
48
+
49
+ assert "backends" in kwargs, (
50
+ "`backends` must be provided to create nixl transfer channel."
51
+ )
52
+ transfer_channel = NixlChannel(
53
+ async_mode=async_mode,
54
+ role=role,
55
+ buffer_ptr=buffer_ptr,
56
+ buffer_size=buffer_size,
57
+ align_bytes=align_bytes,
58
+ tp_rank=tp_rank,
59
+ peer_init_url=peer_init_url,
60
+ device=device,
61
+ **kwargs,
62
+ )
63
+ return transfer_channel
64
+
65
+ if channel_type == "mock_memory":
66
+ # First Party
67
+ from lmcache.v1.transfer_channel.mock_memory_channel import (
68
+ MockMemoryChannel,
69
+ )
70
+
71
+ mock_memory_channel: BaseTransferChannel = MockMemoryChannel(
72
+ async_mode=async_mode,
73
+ role=role,
74
+ buffer_ptr=buffer_ptr,
75
+ buffer_size=buffer_size,
76
+ align_bytes=align_bytes,
77
+ tp_rank=tp_rank,
78
+ peer_init_url=peer_init_url,
79
+ **kwargs,
80
+ )
81
+ return mock_memory_channel
82
+
83
+ raise ValueError(f"Unsupported channel type: {channel_type}")
@@ -0,0 +1,285 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Standard
3
+ from typing import Optional, Union
4
+ import abc
5
+
6
+ # Third Party
7
+ import msgspec
8
+ import zmq
9
+
10
+ # First Party
11
+ from lmcache.v1.memory_management import MemoryObj
12
+ from lmcache.v1.transfer_channel.transfer_utils import (
13
+ InitSideMsgBase,
14
+ InitSideRetMsgBase,
15
+ P2PInitSideMsg,
16
+ P2PInitSideRetMsg,
17
+ SideMsg,
18
+ )
19
+
20
+
21
+ class BaseTransferChannel(metaclass=abc.ABCMeta):
22
+ ### Initialization-related functions ###
23
+ @abc.abstractmethod
24
+ def lazy_init_peer_connection(
25
+ self,
26
+ local_id: str,
27
+ peer_id: str,
28
+ peer_init_url: str,
29
+ init_side_msg: Optional[InitSideMsgBase] = None,
30
+ ) -> Optional[InitSideRetMsgBase]:
31
+ """
32
+ Lazily initialize the connection to a peer.
33
+
34
+ :param local_id: The ID of itself.
35
+ peer_id: The ID of the peer to connect to.
36
+ peer_init_url: The URL used to initialize the connection.
37
+ init_side_msg: An optional side message to be sent to the peer
38
+ during initialization.
39
+
40
+ :return: An optional side message received from the peer.
41
+ """
42
+
43
+ raise NotImplementedError
44
+
45
+ @abc.abstractmethod
46
+ async def async_lazy_init_peer_connection(
47
+ self,
48
+ local_id: str,
49
+ peer_id: str,
50
+ peer_init_url: str,
51
+ init_side_msg: Optional[InitSideMsgBase] = None,
52
+ ) -> Optional[InitSideRetMsgBase]:
53
+ """
54
+ Async version of `lazy_init_peer_connection`.
55
+ """
56
+
57
+ raise NotImplementedError
58
+
59
+ @abc.abstractmethod
60
+ def remote_xfer_handler_exists(self, receiver_or_sender_id: str) -> bool:
61
+ """
62
+ Check if the remote transfer handler exists.
63
+
64
+ :param receiver_or_sender_id: The ID of the receiver or sender.
65
+
66
+ :return: True if the remote transfer handler exists, False otherwise.
67
+ """
68
+ raise NotImplementedError
69
+
70
+ def handle_init_side_msg(
71
+ self,
72
+ req: InitSideMsgBase,
73
+ ) -> InitSideRetMsgBase:
74
+ """
75
+ Handle side messages during initialization.
76
+
77
+ :param req: The initialization-related side message
78
+ received from the peer.
79
+
80
+ :return: A side message to be sent back to the peer.
81
+ """
82
+ if isinstance(req, P2PInitSideMsg):
83
+ assert hasattr(self, "peer_lookup_url"), (
84
+ "P2PInitSideMsg requires `peer_lookup_url` attribute."
85
+ )
86
+ return P2PInitSideRetMsg(
87
+ peer_lookup_url=self.peer_lookup_url,
88
+ )
89
+ else:
90
+ raise ValueError(f"Unsupported InitSideMsg type: {type(req)}")
91
+
92
+ def send_init_side_msg(
93
+ self,
94
+ init_tmp_socket: zmq.Socket,
95
+ init_side_msg: InitSideMsgBase,
96
+ ) -> InitSideRetMsgBase:
97
+ """
98
+ Send side messages during initialization.
99
+
100
+ :param socket: The ZMQ socket used for sending the message.
101
+ :param init_side_msg: The initialization-related side message
102
+ to be sent to the peer.
103
+
104
+ :return: A side message received from the peer.
105
+ """
106
+ init_msg_bytes = msgspec.msgpack.encode(init_side_msg)
107
+ init_tmp_socket.send(init_msg_bytes)
108
+
109
+ init_ret_msg_bytes = init_tmp_socket.recv()
110
+ init_ret_msg = msgspec.msgpack.decode(
111
+ init_ret_msg_bytes,
112
+ type=SideMsg,
113
+ )
114
+
115
+ return init_ret_msg
116
+
117
+ async def async_send_init_side_msg(
118
+ self,
119
+ init_tmp_socket: zmq.Socket,
120
+ init_side_msg: InitSideMsgBase,
121
+ ) -> InitSideRetMsgBase:
122
+ """
123
+ Async version of send_init_side_msg.
124
+ """
125
+ init_msg_bytes = msgspec.msgpack.encode(init_side_msg)
126
+ await init_tmp_socket.send(init_msg_bytes)
127
+
128
+ init_ret_msg_bytes = await init_tmp_socket.recv()
129
+ init_ret_msg = msgspec.msgpack.decode(
130
+ init_ret_msg_bytes,
131
+ type=SideMsg,
132
+ )
133
+
134
+ return init_ret_msg
135
+
136
+ ### Utility functions ###
137
+ @abc.abstractmethod
138
+ def get_local_mem_indices(
139
+ self, objects: Union[list[bytes], list[MemoryObj]]
140
+ ) -> list[int]:
141
+ """
142
+ Get the memory indices of objects.
143
+
144
+ :param objects: A list of bytes or MemoryObj to be checked.
145
+
146
+ :return: The memory indices of the objects.
147
+ """
148
+ raise NotImplementedError
149
+
150
+ ### Send and Recv must be called in pair ###
151
+ @abc.abstractmethod
152
+ def batched_send(
153
+ self,
154
+ objects: Union[list[bytes], list[MemoryObj]],
155
+ transfer_spec: Optional[dict] = None,
156
+ ) -> int:
157
+ """
158
+ Send a batch of data through the channel.
159
+
160
+ :param objects: A list of bytes or MemoryObj to be sent.
161
+ :param transfer_spec: Additional specifications for the transfer.
162
+
163
+ :return: Number of successfully transferred objects.
164
+ """
165
+ raise NotImplementedError
166
+
167
+ @abc.abstractmethod
168
+ def batched_recv(
169
+ self,
170
+ buffers: Union[list[bytes], list[MemoryObj]],
171
+ transfer_spec: Optional[dict] = None,
172
+ ) -> int:
173
+ """
174
+ Receive a batch of data through the channel.
175
+
176
+ :param buffer: A list of bytes or MemoryObj to store the received data.
177
+ :param transfer_spec: Additional specifications for the transfer.
178
+
179
+ :return: Number of successfully transferred objects.
180
+ """
181
+ raise NotImplementedError
182
+
183
+ @abc.abstractmethod
184
+ async def async_batched_send(
185
+ self,
186
+ objects: Union[list[bytes], list[MemoryObj]],
187
+ transfer_spec: Optional[dict] = None,
188
+ ) -> int:
189
+ """
190
+ Async send a batch of data through the channel.
191
+
192
+ :param objects: A list of bytes or MemoryObj to be sent.
193
+ :param transfer_spec: Additional specifications for the transfer.
194
+
195
+ :return: Number of successfully transferred objects.
196
+ """
197
+ raise NotImplementedError
198
+
199
+ @abc.abstractmethod
200
+ async def async_batched_recv(
201
+ self,
202
+ buffers: Union[list[bytes], list[MemoryObj]],
203
+ transfer_spec: Optional[dict] = None,
204
+ ) -> int:
205
+ """
206
+ Async receive a batch of data through the channel.
207
+
208
+ :param buffers: A list of bytes or MemoryObj to store the received data.
209
+ :param transfer_spec: Additional specifications for the transfer.
210
+
211
+ :return: Number of successfully transferred objects.
212
+ """
213
+ raise NotImplementedError
214
+
215
+ ### Read and Write only need to be called on one side ###
216
+ @abc.abstractmethod
217
+ def batched_write(
218
+ self,
219
+ objects: Union[list[bytes], list[MemoryObj]],
220
+ transfer_spec: Optional[dict] = None,
221
+ ) -> int:
222
+ """
223
+ Write a batch of data through the channel.
224
+
225
+ :param objects: A list of bytes or MemoryObj to be written.
226
+ :param transfer_spec: Additional specifications for the transfer.
227
+
228
+ :return: Number of successfully transferred objects.
229
+ """
230
+ raise NotImplementedError
231
+
232
+ @abc.abstractmethod
233
+ def batched_read(
234
+ self,
235
+ buffers: Union[list[bytes], list[MemoryObj]],
236
+ transfer_spec: Optional[dict] = None,
237
+ ) -> int:
238
+ """
239
+ Read a batch of data through the channel.
240
+
241
+ :param buffers: A list of bytes or MemoryObj to store the read data.
242
+ :param transfer_spec: Additional specifications for the transfer.
243
+
244
+ :return: Number of successfully transferred objects.
245
+ """
246
+ raise NotImplementedError
247
+
248
+ @abc.abstractmethod
249
+ async def async_batched_write(
250
+ self,
251
+ objects: Union[list[bytes], list[MemoryObj]],
252
+ transfer_spec: Optional[dict] = None,
253
+ ) -> int:
254
+ """
255
+ Async write a batch of data through the channel.
256
+
257
+ :param objects: A list of bytes or MemoryObj to be written.
258
+ :param transfer_spec: Additional specifications for the transfer.
259
+
260
+ :return: Number of successfully transferred objects.
261
+ """
262
+ raise NotImplementedError
263
+
264
+ @abc.abstractmethod
265
+ async def async_batched_read(
266
+ self,
267
+ buffers: Union[list[bytes], list[MemoryObj]],
268
+ transfer_spec: Optional[dict] = None,
269
+ ) -> int:
270
+ """
271
+ Async read a batch of data through the channel.
272
+
273
+ :param buffers: A list of bytes or MemoryObj to store the read data.
274
+ :param transfer_spec: Additional specifications for the transfer.
275
+
276
+ :return: Number of successfully transferred objects.
277
+ """
278
+ raise NotImplementedError
279
+
280
+ @abc.abstractmethod
281
+ def close(self) -> None:
282
+ """
283
+ Close the transfer channel and release any resources.
284
+ """
285
+ raise NotImplementedError
@@ -0,0 +1,156 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Standard
3
+ from typing import Optional, Union
4
+ import asyncio
5
+
6
+ # Third Party
7
+ import torch
8
+
9
+ # First Party
10
+ from lmcache.logging import init_logger
11
+ from lmcache.v1.memory_management import MemoryObj
12
+ from lmcache.v1.transfer_channel.py_socket_channel import PySocketChannel
13
+
14
+ logger = init_logger(__name__)
15
+
16
+
17
+ # Data plane: Global shared data store for simulating data transfer
18
+ # within a single process. This is a process-local Python dict,
19
+ # NOT shared across processes or machines.
20
+ _GLOBAL_DATA_STORE: dict[str, dict[int, torch.Tensor]] = {}
21
+
22
+
23
+ class MockMemoryChannel(PySocketChannel):
24
+ """
25
+ Mock memory-based transfer channel for single-process testing.
26
+
27
+ Control plane: Inherits ZMQ-based handshake from PySocketChannel.
28
+ Data plane: Uses global dict to simulate tensor transfer.
29
+
30
+ Only works within a single process. For production use NixlChannel.
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ async_mode: bool = False,
36
+ **kwargs,
37
+ ):
38
+ super().__init__(async_mode=async_mode, **kwargs)
39
+
40
+ ############################################################
41
+ # Data plane: Override hook to initialize global data store
42
+ ############################################################
43
+ def _on_peer_connected(self, peer_url: str):
44
+ """Initialize data store when a peer connects"""
45
+ if peer_url not in _GLOBAL_DATA_STORE:
46
+ _GLOBAL_DATA_STORE[peer_url] = {}
47
+
48
+ ############################################################
49
+ # Data plane: Utility functions
50
+ ############################################################
51
+ def get_local_mem_indices(
52
+ self, objects: Union[list[bytes], list[MemoryObj]]
53
+ ) -> list[int]:
54
+ local_indices = []
55
+ if isinstance(objects[0], MemoryObj):
56
+ for mem_obj in objects:
57
+ assert isinstance(mem_obj, MemoryObj)
58
+ local_indices.append(mem_obj.meta.address)
59
+ elif isinstance(objects[0], bytes):
60
+ raise NotImplementedError(
61
+ "Sending raw bytes is not supported in MockMemoryChannel"
62
+ )
63
+ return local_indices
64
+
65
+ ############################################################
66
+ # Data plane: Send/Recv functions (not implemented)
67
+ ############################################################
68
+ def batched_send(
69
+ self,
70
+ objects: Union[list[bytes], list[MemoryObj]],
71
+ transfer_spec: Optional[dict] = None,
72
+ ) -> int:
73
+ raise NotImplementedError
74
+
75
+ def batched_recv(
76
+ self,
77
+ buffers: Union[list[bytes], list[MemoryObj]],
78
+ transfer_spec: Optional[dict] = None,
79
+ ) -> int:
80
+ raise NotImplementedError
81
+
82
+ async def async_batched_send(
83
+ self,
84
+ objects: Union[list[bytes], list[MemoryObj]],
85
+ transfer_spec: Optional[dict] = None,
86
+ ) -> int:
87
+ raise NotImplementedError
88
+
89
+ async def async_batched_recv(
90
+ self,
91
+ buffers: Union[list[bytes], list[MemoryObj]],
92
+ transfer_spec: Optional[dict] = None,
93
+ ) -> int:
94
+ raise NotImplementedError
95
+
96
+ ############################################################
97
+ # Data plane: Read/Write functions (global dict simulation)
98
+ ############################################################
99
+ def remote_xfer_handler_exists(self, receiver_or_sender_id: str) -> bool:
100
+ return True
101
+
102
+ def batched_write(
103
+ self,
104
+ objects: Union[list[bytes], list[MemoryObj]],
105
+ transfer_spec: Optional[dict] = None,
106
+ ) -> int:
107
+ raise NotImplementedError("Sync mode not supported in MockMemoryChannel")
108
+
109
+ def batched_read(
110
+ self,
111
+ buffers: Union[list[bytes], list[MemoryObj]],
112
+ transfer_spec: Optional[dict] = None,
113
+ ) -> int:
114
+ raise NotImplementedError("Sync mode not supported in MockMemoryChannel")
115
+
116
+ async def async_batched_write(
117
+ self,
118
+ objects: Union[list[bytes], list[MemoryObj]],
119
+ transfer_spec: Optional[dict] = None,
120
+ ) -> int:
121
+ """Write tensors to global dict to simulate data transfer"""
122
+ assert transfer_spec is not None
123
+
124
+ receiver_id = transfer_spec["receiver_id"]
125
+ remote_indexes = transfer_spec["remote_indexes"]
126
+
127
+ for obj, remote_idx in zip(objects, remote_indexes, strict=True):
128
+ if isinstance(obj, MemoryObj) and obj.tensor is not None:
129
+ if receiver_id not in _GLOBAL_DATA_STORE:
130
+ _GLOBAL_DATA_STORE[receiver_id] = {}
131
+ _GLOBAL_DATA_STORE[receiver_id][remote_idx] = obj.tensor.clone()
132
+
133
+ await asyncio.sleep(0.001)
134
+ return len(objects)
135
+
136
+ async def async_batched_read(
137
+ self,
138
+ buffers: Union[list[bytes], list[MemoryObj]],
139
+ transfer_spec: Optional[dict] = None,
140
+ ) -> int:
141
+ """Read tensors from global dict to simulate data transfer"""
142
+ assert transfer_spec is not None
143
+
144
+ sender_id = transfer_spec["sender_id"]
145
+ remote_indexes = transfer_spec["remote_indexes"]
146
+
147
+ for buf, remote_idx in zip(buffers, remote_indexes, strict=True):
148
+ if isinstance(buf, MemoryObj) and buf.tensor is not None:
149
+ if (
150
+ sender_id in _GLOBAL_DATA_STORE
151
+ and remote_idx in _GLOBAL_DATA_STORE[sender_id]
152
+ ):
153
+ buf.tensor.copy_(_GLOBAL_DATA_STORE[sender_id][remote_idx])
154
+
155
+ await asyncio.sleep(0.001)
156
+ return len(buffers)