[Remote Connector]: cpp multi-threaded RESP#2541
Conversation
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Summary of ChangesHello @sammshen, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a substantial performance upgrade for LMCache's remote key-value store capabilities by implementing a new multi-threaded C++ client for the Redis RESP protocol. This client is exposed to Python via efficient bindings that minimize overhead, allowing for non-blocking operations and significantly boosting data transfer rates. The integration provides LMCache with a high-throughput remote connector, although further work on multiprocessing mode is identified to fully leverage the new client's potential within LMCache. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a high-performance, multi-threaded C++ RESP client to improve throughput for remote KV cache operations, utilizing modern C++ features for concurrency and an eventfd-based mechanism for asyncio integration. It also includes Python bindings, a new RESPConnector for the LMCache framework, and related refactoring. While the overall design is solid, a security audit identified several critical and medium severity issues, including a potential division-by-zero crash in batch operations, a Python GIL violation during object destruction in background threads, a race condition in the asynchronous future registration logic, and the lack of socket timeouts in worker threads which could lead to indefinite hangs. Additionally, a critical issue was found in the RESP protocol parsing that could lead to connection failures (e.g., key not found). Further improvements are needed in error handling, performance, and code clarity.
| static void do_get_into(WorkerConn& conn, const std::string& key, void* buf, | ||
| size_t len) { | ||
| // we only read exactly chunk_bytes bytes (save_unfull_chunk must be off) | ||
| if (len != conn.chunk_bytes) { | ||
| throw std::runtime_error("buffer size mismatch"); | ||
| } | ||
|
|
||
| // build key header (can't pre-allocate) | ||
| std::string key_header = conn.make_key_header(key); | ||
|
|
||
| // send GET cmd | ||
| // iovec let's us combine pre-built parts and dynamic strings | ||
| conn.send_multipart({{conn.get_prefix.data(), conn.get_prefix.size()}, | ||
| {key_header.data(), key_header.size()}}); | ||
|
|
||
| // parse in 3 steps | ||
|
|
||
| // 1. parse the size header and validate | ||
| std::vector<char> size_header_buf(conn.size_header.size()); | ||
| conn.recv_exactly(size_header_buf.data(), size_header_buf.size()); | ||
| if (std::memcmp(size_header_buf.data(), conn.size_header.data(), | ||
| conn.size_header.size()) != 0) { | ||
| throw std::runtime_error("GET: size header mismatch"); | ||
| } | ||
|
|
||
| // 2. parse the payload (KV Cache) | ||
| conn.recv_exactly(buf, len); | ||
|
|
||
| // 3. parse the trailer and validate | ||
| char trailer[WorkerConn::crlf_len]; | ||
| conn.recv_exactly(trailer, WorkerConn::crlf_len); | ||
| if (std::memcmp(trailer, conn.crlf, WorkerConn::crlf_len) != 0) { | ||
| throw std::runtime_error("GET: trailer mismatch"); | ||
| } | ||
| } |
There was a problem hiding this comment.
The current RESP parsing logic is very fragile as it assumes a fixed response structure for GET operations. It doesn't handle Redis error responses (e.g., -ERR ...) or nil responses for non-existent keys ($-1\r\n). If Redis returns an unexpected response, the client will likely desynchronize from the TCP stream, leading to cascading failures for all subsequent operations on that connection.
To make this more robust, the parsing logic should inspect the first byte of the response to determine its type (e.g., + for simple string, $ for bulk string, - for error, : for integer) and parse the rest of the response accordingly. This is crucial for handling cases like a key not being found during a GET operation.
A similar issue exists in do_set_from and do_exists.
There was a problem hiding this comment.
I think this suggestion is reasonable. The no parsing optimization might be a little aggressive. Parsing only the first byte avoid O(n) equality check.
| fut.set_exception(exc) | ||
| self._pending.clear() |
There was a problem hiding this comment.
In RESPClient, the submit_* methods call the native client and then register a future using the returned future_id. There is a race condition where the native worker thread could complete the operation and signal the event_fd before the future is registered in self._pending. If this happens, _on_ready will ignore the completion because the future_id is not yet in self._pending, and the future will never be resolved, leading to a hang.
Recommendation: The future_id should be known or reserved before the task is submitted to the native worker, allowing the future to be registered before the worker can possibly complete the task.
| std::string make_key_header(const std::string& key) { | ||
| std::ostringstream oss; | ||
| oss << "$" << key.size() << "\r\n" << key << "\r\n"; | ||
| return oss.str(); | ||
| } |
There was a problem hiding this comment.
The make_key_header function uses std::ostringstream to construct the key header string for each request. While convenient, this can introduce performance overhead due to repeated dynamic memory allocations in a performance-critical path.
For a high-throughput client, consider optimizing this by using a pre-allocated buffer (e.g., thread-local) with snprintf, or a more efficient string building mechanism to avoid allocations on each call.
There was a problem hiding this comment.
The make_key_header function uses std::ostringstream to construct the key header string for each request. While convenient, this can introduce performance overhead due to repeated dynamic memory allocations in a performance-critical path.
For a high-throughput client, consider optimizing this by using a pre-allocated buffer (e.g., thread-local) with snprintf, or a more efficient string building mechanism to avoid allocations on each call.
I agree with Gemini's opinion here. (But only when we can have an upper-bound on the key's size)
|
|
||
| # sync and asyncio wrapper around the LMCacheRedisClient | ||
| # the pybinding interface allows us to work with both sync and async code | ||
| class RESPClient: |
There was a problem hiding this comment.
|
do you have any ideas why the github runners cannot run the free disk space action? Update: should be fixed by #2543 |
There was a problem hiding this comment.
follow up: whether to have "pin"/"lock" semantics
There was a problem hiding this comment.
doesn't seem to be in RESP right now
| tile_req.buf_owners.push_back(mv); | ||
| } | ||
|
|
||
| enqueue_request(std::move(tile_req)); |
There was a problem hiding this comment.
double check whether std::move and auto move constructor can work on all the fields inside Request struct (especially py::object)
ApostaC
left a comment
There was a problem hiding this comment.
Did a pass. The major things
- Try to avoid having python-related stuff in
resp.handresp.cpp - only keep the "batched" primitives
| self.storage_manager.remove(key) | ||
| memory_obj.ref_count_down() | ||
|
|
||
| retrieve_stats.end_time = time.perf_counter() |
There was a problem hiding this comment.
Why do we have this in this PR?
There was a problem hiding this comment.
needed to check the throughput. this has been broken for a while now
There was a problem hiding this comment.
I can separate a new PR for this but this PR needs it as well to test so it will create redundant changes
There was a problem hiding this comment.
Can we rename it as "full_chunk_size_bytes"? It's clearer because full_chunk_bytes sounds like a data chunk of bytes.
Btw, this name change can be separated to another PR to keep this PR clean.
There was a problem hiding this comment.
Is it possible to avoid having py-related stuff in resp.h and resp.cpp? Let's try to put all the python-related types and operations into pybind.cpp.
FYI, py::list can be directly (and automatically) converted to std::vector if we include pybind11/stl.h (https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html)
We can also manually convert py::memoryview to std::vector as well (or maybe there are better practices).
There was a problem hiding this comment.
By doing this, we can also have more freedom to release GIL. See: https://pybind11.readthedocs.io/en/stable/advanced/misc.html#global-interpreter-lock-gil
The Python C API dictates that the Global Interpreter Lock (GIL) must always be held by the current thread to safely access Python objects. As a result, when Python calls into C++ via pybind11 the GIL must be held, and pybind11 will never implicitly release the GIL.
There was a problem hiding this comment.
Yes GIL only needed for py::object and py::handle so this will clarify where GIL can be released (do scoped release ASAP in every cpp function)
| .def(py::init<std::string, int, size_t, int>(), py::arg("host"), | ||
| py::arg("port"), py::arg("chunk_bytes"), py::arg("num_workers")) | ||
| .def("event_fd", &MultiRESPClient::event_fd) | ||
| .def("submit_get", &MultiRESPClient::submit_get, py::arg("key"), | ||
| py::arg("memoryview")) | ||
| .def("submit_set", &MultiRESPClient::submit_set, py::arg("key"), | ||
| py::arg("memoryview")) | ||
| .def("submit_exists", &MultiRESPClient::submit_exists, py::arg("key")) | ||
| .def("submit_batch_get", &MultiRESPClient::submit_batch_get, | ||
| py::arg("keys"), py::arg("memoryviews")) | ||
| .def("submit_batch_set", &MultiRESPClient::submit_batch_set, | ||
| py::arg("keys"), py::arg("memoryviews")) | ||
| .def("submit_batch_exists", &MultiRESPClient::submit_batch_exists, | ||
| py::arg("keys")) | ||
| .def("drain_completions", &MultiRESPClient::drain_completions) | ||
| .def("close", &MultiRESPClient::close); |
There was a problem hiding this comment.
If we removed all the py-related stuff from resp.h and resp.cpp, we could have a few very simple lambda expressions to do the type conversion here.
| uint64_t submit_get(const std::string& key, py::memoryview mv); | ||
| uint64_t submit_set(const std::string& key, py::memoryview mv); | ||
| uint64_t submit_exists(const std::string& key); |
There was a problem hiding this comment.
We can force all the operations to be "batched" and remove these three functions. It can simplify the cpp implementation.
| this->host = host; | ||
| this->port = port; | ||
| this->chunk_bytes = chunk_bytes; | ||
|
|
||
| // reusable headers (for scatter/gather) | ||
|
|
||
| { | ||
| std::ostringstream oss; | ||
| oss << "$" << chunk_bytes << "\r\n"; | ||
| size_header = oss.str(); | ||
| } | ||
|
|
||
| get_prefix = "*2\r\n$3\r\nGET\r\n"; | ||
| set_prefix = "*3\r\n$3\r\nSET\r\n"; | ||
| exists_prefix = "*2\r\n$6\r\nEXISTS\r\n"; |
There was a problem hiding this comment.
Generally, the code here can be put into the constructor.
Also, the get_prefix, set_prefix, and exists_prefix can be constexpr std::string_view IIUC?
| std::string make_key_header(const std::string& key) { | ||
| std::ostringstream oss; | ||
| oss << "$" << key.size() << "\r\n" << key << "\r\n"; | ||
| return oss.str(); | ||
| } |
There was a problem hiding this comment.
The make_key_header function uses std::ostringstream to construct the key header string for each request. While convenient, this can introduce performance overhead due to repeated dynamic memory allocations in a performance-critical path.
For a high-throughput client, consider optimizing this by using a pre-allocated buffer (e.g., thread-local) with snprintf, or a more efficient string building mechanism to avoid allocations on each call.
I agree with Gemini's opinion here. (But only when we can have an upper-bound on the key's size)
| MultiRESPClient::MultiRESPClient(std::string host, int port, size_t chunk_bytes, | ||
| int num_workers) | ||
| : host_(std::move(host)), |
There was a problem hiding this comment.
What's the reason to have std::string host and host_(std::move(host)) instead of using const std::string &host) with host_(host)?
There was a problem hiding this comment.
Since host will always be stored in the object (it's a "sink"), this pattern lets the compiler choose the optimal path based on what the caller provides, without needing overloads.
https://stackoverflow.com/questions/21035417/is-the-pass-by-value-and-then-move-construct-a-bad-idiom
| // these will be the keys and buffers that this Request is responsible for | ||
| std::vector<std::string> keys; | ||
| std::vector<void*> buf_ptrs; | ||
| std::vector<py::object> buf_owners; |
There was a problem hiding this comment.
I'm not an expert here, but I do want to get rid of buf_owners (and buf_owner) here.
From pybind11's doc, I do see we can do inc_ref and dec_ref on the python objects, including py::memoryview (see https://pybind11.readthedocs.io/en/stable/reference.html#without-reference-counting)
Not sure what the best practice is, but let's investigate and learn.
There was a problem hiding this comment.
One thing we need to be careful about is that we need to do dec_ref when the failure happens. Since the tasks are executed asynchronously, I'm not sure what's the best place to do the dec_ref.
There was a problem hiding this comment.
IMO, the best place is the destructor.
There was a problem hiding this comment.
I think we can get rid of buf_owners since we can make the assumption in LMCache use case that the memory objects will not be garbage collected
| void MultiRESPClient::enqueue_request(Request&& req) { | ||
| { | ||
| std::lock_guard<std::mutex> lk(req_mu_); | ||
| requests_.push(std::move(req)); |
There was a problem hiding this comment.
we can probably do requests_.emplace(req) here (see https://en.cppreference.com/w/cpp/container/queue/emplace.html)
There was a problem hiding this comment.
the req struct already exists (and is populated dynamically) so this does nothing? unless the cpp compiler is a super genius and can somehow figure this out.
DongDongJu
left a comment
There was a problem hiding this comment.
Hello @sammshen, Thanks for the hard work.
It seems very similar like what I currently do right now.
Left few comments and will revisit tomorrow afternoon.
| std::string first_error; | ||
|
|
||
| // for batch exists, store the boolean results (0/1) | ||
| // IMPORTANT: not vector<bool> due to concurrent write data race |
| // these will be the keys and buffers that this Request is responsible for | ||
| std::vector<std::string> keys; | ||
| std::vector<void*> buf_ptrs; | ||
| std::vector<py::object> buf_owners; |
There was a problem hiding this comment.
IMO, the best place is the destructor.
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
…o redis-cpp-client
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
DongDongJu
left a comment
There was a problem hiding this comment.
Overall looks good to me.
Could you help me to understand the info.size issue question I left?
Let me test it tomorrow.
|
|
||
| # future_id -> (Future, op_name) | ||
| # we support both types of futures since we only their basic interface | ||
| self._pending: Dict[ |
There was a problem hiding this comment.
Is this for preventing the python memory gc?
There was a problem hiding this comment.
this is to find the python future to which a completion belongs to from the cpp side.
cpp wakes up python via eventfd and outputs (future_id, ok, result_bool, error, result_bools) and python side needs to populate the future indexed by the future_id
There was a problem hiding this comment.
Okay then it does prevent GC of python future object not memoryview.
There was a problem hiding this comment.
Is there any possibility that completion drained before _pending insert?
If then we need another types of structure that Tuple[pending_future structure, str, Tuple[memoryview, ...]] types of thing for safe resolving. but It seems this case didnt happened in my test case.
So, just left as a concern in here.
There was a problem hiding this comment.
this will not happen because the callback is not preemptive at the python level and the submission is non-blocking!
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
Signed-off-by: Samuel Shen <slshen@uchciago.edu>
DongDongJu
left a comment
There was a problem hiding this comment.
Generally LGTM.
I checked that functionally working.
but I left on concern for memoryview gc issue.
We can take care it when it happened.
|
|
||
| # future_id -> (Future, op_name) | ||
| # we support both types of futures since we only their basic interface | ||
| self._pending: Dict[ |
There was a problem hiding this comment.
Okay then it does prevent GC of python future object not memoryview.
|
|
||
| # future_id -> (Future, op_name) | ||
| # we support both types of futures since we only their basic interface | ||
| self._pending: Dict[ |
There was a problem hiding this comment.
Is there any possibility that completion drained before _pending insert?
If then we need another types of structure that Tuple[pending_future structure, str, Tuple[memoryview, ...]] types of thing for safe resolving. but It seems this case didnt happened in my test case.
So, just left as a concern in here.
|
Addressed correctness concern @DongDongJu . Thanks for your review! |
|
Potential future ideas: |
|
can follow #2607 to extract out some interfaces (batching, GIL release patterns etc.) |
|
@sammshen Would you like to implement a fs connector also? |
|
BTW, as discussed with @sammshen and @DongDongJu , #2607 may be a reference. We can do an abstraction to
|
maobaolong
left a comment
There was a problem hiding this comment.
LGTM, thanks for this great work!
* initial commit Signed-off-by: Samuel Shen <slshen@uchciago.edu> * initial pybinding Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix race condition Signed-off-by: Samuel Shen <slshen@uchciago.edu> * remove resp.h import in csrc/pybind.cpp Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fixing installation Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add batched exists Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add working example Signed-off-by: Samuel Shen <slshen@uchciago.edu> * batched_contains is sync Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix cache engine time logging Signed-off-by: Samuel Shen <slshen@uchciago.edu> * address cpp side comments Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix benchmarking test script Signed-off-by: Samuel Shen <slshen@uchciago.edu> * create single resp client file Signed-off-by: Samuel Shen <slshen@uchciago.edu> * dynamic chunk_bytes Signed-off-by: Samuel Shen <slshen@uchciago.edu> * nit renaming Signed-off-by: Samuel Shen <slshen@uchciago.edu> * readme nit Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix rust raw block backend Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix non CUDA UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * revert test.yml Signed-off-by: Samuel Shen <slshen@uchciago.edu> * delete **.cpp and **.h path for non cuda UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add RESP unit tests Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add __init__.py to tests/v1/storage_backend/ Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add fixture for resp tests Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add authentication Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix UT with authentication Signed-off-by: Samuel Shen <slshen@uchciago.edu> * found golden payload size Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add no build isolation Signed-off-by: Samuel Shen <slshen@uchciago.edu> --------- Signed-off-by: Samuel Shen <slshen@uchciago.edu> Co-authored-by: Samuel Shen <slshen@uchciago.edu>
* initial commit Signed-off-by: Samuel Shen <slshen@uchciago.edu> * initial pybinding Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix race condition Signed-off-by: Samuel Shen <slshen@uchciago.edu> * remove resp.h import in csrc/pybind.cpp Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fixing installation Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add batched exists Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add working example Signed-off-by: Samuel Shen <slshen@uchciago.edu> * batched_contains is sync Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix cache engine time logging Signed-off-by: Samuel Shen <slshen@uchciago.edu> * address cpp side comments Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix benchmarking test script Signed-off-by: Samuel Shen <slshen@uchciago.edu> * create single resp client file Signed-off-by: Samuel Shen <slshen@uchciago.edu> * dynamic chunk_bytes Signed-off-by: Samuel Shen <slshen@uchciago.edu> * nit renaming Signed-off-by: Samuel Shen <slshen@uchciago.edu> * readme nit Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix rust raw block backend Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix non CUDA UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * revert test.yml Signed-off-by: Samuel Shen <slshen@uchciago.edu> * delete **.cpp and **.h path for non cuda UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add RESP unit tests Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add __init__.py to tests/v1/storage_backend/ Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add fixture for resp tests Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add authentication Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix UT with authentication Signed-off-by: Samuel Shen <slshen@uchciago.edu> * found golden payload size Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add no build isolation Signed-off-by: Samuel Shen <slshen@uchciago.edu> --------- Signed-off-by: Samuel Shen <slshen@uchciago.edu> Co-authored-by: Samuel Shen <slshen@uchciago.edu>
* initial commit Signed-off-by: Samuel Shen <slshen@uchciago.edu> * initial pybinding Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix race condition Signed-off-by: Samuel Shen <slshen@uchciago.edu> * remove resp.h import in csrc/pybind.cpp Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fixing installation Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add batched exists Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add working example Signed-off-by: Samuel Shen <slshen@uchciago.edu> * batched_contains is sync Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix cache engine time logging Signed-off-by: Samuel Shen <slshen@uchciago.edu> * address cpp side comments Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix benchmarking test script Signed-off-by: Samuel Shen <slshen@uchciago.edu> * create single resp client file Signed-off-by: Samuel Shen <slshen@uchciago.edu> * dynamic chunk_bytes Signed-off-by: Samuel Shen <slshen@uchciago.edu> * nit renaming Signed-off-by: Samuel Shen <slshen@uchciago.edu> * readme nit Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix rust raw block backend Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix non CUDA UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * revert test.yml Signed-off-by: Samuel Shen <slshen@uchciago.edu> * delete **.cpp and **.h path for non cuda UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add RESP unit tests Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add __init__.py to tests/v1/storage_backend/ Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add fixture for resp tests Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add authentication Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix UT with authentication Signed-off-by: Samuel Shen <slshen@uchciago.edu> * found golden payload size Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add no build isolation Signed-off-by: Samuel Shen <slshen@uchciago.edu> --------- Signed-off-by: Samuel Shen <slshen@uchciago.edu> Co-authored-by: Samuel Shen <slshen@uchciago.edu>
* initial commit Signed-off-by: Samuel Shen <slshen@uchciago.edu> * initial pybinding Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix race condition Signed-off-by: Samuel Shen <slshen@uchciago.edu> * remove resp.h import in csrc/pybind.cpp Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fixing installation Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add batched exists Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add working example Signed-off-by: Samuel Shen <slshen@uchciago.edu> * batched_contains is sync Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix cache engine time logging Signed-off-by: Samuel Shen <slshen@uchciago.edu> * address cpp side comments Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix benchmarking test script Signed-off-by: Samuel Shen <slshen@uchciago.edu> * create single resp client file Signed-off-by: Samuel Shen <slshen@uchciago.edu> * dynamic chunk_bytes Signed-off-by: Samuel Shen <slshen@uchciago.edu> * nit renaming Signed-off-by: Samuel Shen <slshen@uchciago.edu> * readme nit Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix rust raw block backend Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix non CUDA UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * revert test.yml Signed-off-by: Samuel Shen <slshen@uchciago.edu> * delete **.cpp and **.h path for non cuda UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add RESP unit tests Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add __init__.py to tests/v1/storage_backend/ Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add fixture for resp tests Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add authentication Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix UT with authentication Signed-off-by: Samuel Shen <slshen@uchciago.edu> * found golden payload size Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add no build isolation Signed-off-by: Samuel Shen <slshen@uchciago.edu> --------- Signed-off-by: Samuel Shen <slshen@uchciago.edu> Co-authored-by: Samuel Shen <slshen@uchciago.edu> Signed-off-by: shaoxiawjc <wjc2800@163.com>
* initial commit Signed-off-by: Samuel Shen <slshen@uchciago.edu> * initial pybinding Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix race condition Signed-off-by: Samuel Shen <slshen@uchciago.edu> * remove resp.h import in csrc/pybind.cpp Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fixing installation Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add batched exists Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add working example Signed-off-by: Samuel Shen <slshen@uchciago.edu> * batched_contains is sync Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix cache engine time logging Signed-off-by: Samuel Shen <slshen@uchciago.edu> * address cpp side comments Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix benchmarking test script Signed-off-by: Samuel Shen <slshen@uchciago.edu> * create single resp client file Signed-off-by: Samuel Shen <slshen@uchciago.edu> * dynamic chunk_bytes Signed-off-by: Samuel Shen <slshen@uchciago.edu> * nit renaming Signed-off-by: Samuel Shen <slshen@uchciago.edu> * readme nit Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix rust raw block backend Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix non CUDA UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * revert test.yml Signed-off-by: Samuel Shen <slshen@uchciago.edu> * delete **.cpp and **.h path for non cuda UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add RESP unit tests Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add __init__.py to tests/v1/storage_backend/ Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add fixture for resp tests Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix UT Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add authentication Signed-off-by: Samuel Shen <slshen@uchciago.edu> * fix UT with authentication Signed-off-by: Samuel Shen <slshen@uchciago.edu> * found golden payload size Signed-off-by: Samuel Shen <slshen@uchciago.edu> * add no build isolation Signed-off-by: Samuel Shen <slshen@uchciago.edu> --------- Signed-off-by: Samuel Shen <slshen@uchciago.edu> Co-authored-by: Samuel Shen <slshen@uchciago.edu> Signed-off-by: Aaron Wu <aaron.wu@dell.com>

@ApostaC as discussed, the interface is agnostic to
asyncio.Futureversusconcurrent.future.Futureso can be folded in as a Controller inside MP Mode.This cpp integration has brought the raw client throughput to 10 GB / s (see the
examples/folder addition) from previous 4-5 GB/s limit with python (optimizations are thoroughly documented in/csrc/redis/resp.cpp). LMCache integration now stands at ~7GB/s (compared to previous 0.5 GB/s)