Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
2b6f51d
Merge pull request #23 from Gzure/supercache_dev_ssd_remove
zchuango Aug 10, 2026
192136d
deployment and install
Aug 17, 2026
d584ad7
Merge pull request #31 from Gzure/ssd_remove_fix
Gzure Aug 17, 2026
7762928
add for cvm kvpt
Aug 28, 2026
58e27c5
add log for slot
Aug 28, 2026
f6fae7d
add for fix oplog bug
Aug 28, 2026
8994089
add for fix connect to submaster
Aug 29, 2026
5083079
add for etcd bug
Aug 29, 2026
32bb31a
add inter-master forwarding for putstart and getreplicalist
Aug 29, 2026
88781e7
fix slot ownership oscillation and add inter-master write forwarding
Aug 29, 2026
d0b8192
[Store] Add vchunk configuration and metadata foundations
Aug 26, 2026
9e53c99
[Store] Add vchunk allocation and in-memory master control plane
Aug 26, 2026
4c7b593
[Store] Complete the vchunk client data path
Aug 26, 2026
6f1d787
[Store] Add persistent vchunk recovery and engineering safeguards
Aug 26, 2026
73699eb
[Store] Add vchunk A/B benchmarks and analysis reports
Aug 26, 2026
745bda9
[Store] Fix vchunk recovery and resource lifetimes
Aug 26, 2026
9041094
[Store] Fix address typing in vchunk client tests
Aug 26, 2026
c19e2f4
[Store] Add distributed vchunk performance validation
Aug 27, 2026
7dae78c
[Store] Allow vchunk and HA to be enabled together
Aug 27, 2026
6941a67
[Store] Strengthen vchunk disabled-mode gates and test dependencies
Aug 28, 2026
79b8206
[Store] Adapt vchunk routing and ownership gates for multiple SubMasters
Aug 28, 2026
8009fdd
[Store] Fix vchunk SubMaster concurrency and read lifetimes
Aug 28, 2026
3b6ad80
[Store] Fix vchunk read-lease RPC compilation
Aug 28, 2026
0b4e160
add for fix client ping
Aug 29, 2026
0ac26f2
add for erase segment mount log
Aug 29, 2026
5679b89
Merge pull request #2 from Lzk-1/supercache_ha_vchunk_submaster
wangyuqi0429 Aug 31, 2026
eaeb46b
add for segment mount
Sep 1, 2026
235fd7d
add for slot fence
Sep 1, 2026
00ce997
Merge pull request #45 from wangyuqi0429/supercache_ha
wangyuqi0429 Sep 3, 2026
4058b6e
io_pattern frame
Gzure Sep 1, 2026
cfec19f
io_pattern frame
Gzure Sep 1, 2026
1a19ded
io pattern代码初始步完成
Gzure Sep 2, 2026
efa0ddb
io pattern代码初始步完成
Gzure Sep 2, 2026
3ee7b4f
merge cvm
Gzure Sep 3, 2026
ff0ed45
add cvm support
Gzure Sep 3, 2026
1fc118c
add cvm support
Gzure Sep 3, 2026
d2dd1b8
add cfm client benchmark
Gzure Sep 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,246 changes: 1,246 additions & 0 deletions docs/source/io_pattern_design.md

Large diffs are not rendered by default.

777 changes: 777 additions & 0 deletions docs/yh/deployment.md

Large diffs are not rendered by default.

54 changes: 52 additions & 2 deletions mooncake-common/etcd/etcd_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -811,8 +811,49 @@ func EtcdStoreBatchCreateWrapper(keys **C.char, values **C.char, count C.int, er
return 0
}

//export EtcdStoreBatchPutWithLeaseWrapper
func EtcdStoreBatchPutWithLeaseWrapper(keys **C.char, keySizes *C.int, values **C.char, valueSizes *C.int, count C.int, leaseId int64, errMsg **C.char) int {
cli := getStoreClient()
if cli == nil {
*errMsg = C.CString("etcd client not initialized")
return -1
}

n := int(count)
if n == 0 {
return 0
}

// Unsafe casting to access C arrays as Go slices; key/value buffers are
// binary-safe (carry explicit sizes).
keyPtrs := (*[1 << 28]*C.char)(unsafe.Pointer(keys))[:n:n]
keySizeList := (*[1 << 28]C.int)(unsafe.Pointer(keySizes))[:n:n]
valPtrs := (*[1 << 28]*C.char)(unsafe.Pointer(values))[:n:n]
valSizeList := (*[1 << 28]C.int)(unsafe.Pointer(valueSizes))[:n:n]

ops := make([]clientv3.Op, 0, n)
for i := 0; i < n; i++ {
k := C.GoStringN(keyPtrs[i], keySizeList[i])
v := C.GoStringN(valPtrs[i], valSizeList[i])
// Bind all keys to the single master lease. Caller is responsible for
// fencing (the keys must already be absent / owned by self); this is an
// unconditional atomic batch, so it can also be reused for reaffirm.
ops = append(ops, clientv3.OpPut(k, v, clientv3.WithLease(clientv3.LeaseID(leaseId))))
}

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

_, err := cli.Txn(ctx).Then(ops...).Commit()
if err != nil {
*errMsg = C.CString(err.Error())
return -1
}
return 0
}

//export EtcdStoreTxnCompareAndPutWrapper
func EtcdStoreTxnCompareAndPutWrapper(compareKeys **C.char, compareKeySizes *C.int, compareKinds *C.int, compareValues **C.char, compareValueSizes *C.int, compareCount C.int, putKeys **C.char, putKeySizes *C.int, putValues **C.char, putValueSizes *C.int, putCount C.int, errMsg **C.char) int {
func EtcdStoreTxnCompareAndPutWrapper(compareKeys **C.char, compareKeySizes *C.int, compareKinds *C.int, compareValues **C.char, compareValueSizes *C.int, compareCount C.int, putKeys **C.char, putKeySizes *C.int, putValues **C.char, putValueSizes *C.int, putCount C.int, deleteKeys **C.char, deleteKeySizes *C.int, deleteCount C.int, errMsg **C.char) int {
cli := getStoreClient()
if cli == nil {
*errMsg = C.CString("etcd client not initialized")
Expand All @@ -821,6 +862,7 @@ func EtcdStoreTxnCompareAndPutWrapper(compareKeys **C.char, compareKeySizes *C.i

cmpN := int(compareCount)
putN := int(putCount)
deleteN := int(deleteCount)

cmps := make([]clientv3.Cmp, 0, cmpN)
if cmpN > 0 {
Expand All @@ -844,7 +886,7 @@ func EtcdStoreTxnCompareAndPutWrapper(compareKeys **C.char, compareKeySizes *C.i
}
}

ops := make([]clientv3.Op, 0, putN)
ops := make([]clientv3.Op, 0, putN+deleteN)
if putN > 0 {
putKeyPtrs := (*[1 << 28]*C.char)(unsafe.Pointer(putKeys))[:putN:putN]
putKeySizeList := (*[1 << 28]C.int)(unsafe.Pointer(putKeySizes))[:putN:putN]
Expand All @@ -856,6 +898,14 @@ func EtcdStoreTxnCompareAndPutWrapper(compareKeys **C.char, compareKeySizes *C.i
ops = append(ops, clientv3.OpPut(k, v))
}
}
if deleteN > 0 {
deleteKeyPtrs := (*[1 << 28]*C.char)(unsafe.Pointer(deleteKeys))[:deleteN:deleteN]
deleteKeySizeList := (*[1 << 28]C.int)(unsafe.Pointer(deleteKeySizes))[:deleteN:deleteN]
for i := 0; i < deleteN; i++ {
k := C.GoStringN(deleteKeyPtrs[i], deleteKeySizeList[i])
ops = append(ops, clientv3.OpDelete(k))
}
}

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
Expand Down
31 changes: 23 additions & 8 deletions mooncake-common/include/rpc_client_io_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <shared_mutex>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>

#include <ylt/coro_io/client_pool.hpp>
Expand All @@ -26,9 +27,10 @@ coro_io::io_context_pool& GetRpcClientIoContextPool(uint32_t thread_count) {
}

/**
* A replaceable client pool for callers that communicate with one target at a
* time. Requests retain a shared_ptr to the old pool while they are in flight;
* after an address switch the old pool is destroyed when those requests end.
* A client pool accessor that caches one client pool per target address, so
* callers that alternate between several targets (e.g. submaster routing)
* reuse existing connections instead of recreating a pool on every switch.
* The most recently selected pool is also exposed via GetClientPool().
*/
class RpcClientPool {
public:
Expand All @@ -38,18 +40,22 @@ class RpcClientPool {
explicit RpcClientPool(coro_io::io_context_pool& io_context_pool,
PoolConfig config = {})
: io_context_pool_(io_context_pool), config_(std::move(config)) {
// Address replacement supersedes background recovery of the old host.
// Explicit target selection supersedes background recovery of an old
// host; the pool's own connect/retry still applies per request.
config_.host_alive_detect_duration = std::chrono::seconds(0);
}

std::shared_ptr<ClientPool> GetOrCreateClientPool(
std::string_view address) {
std::lock_guard<std::shared_mutex> lock(mutex_);
if (!client_pool_ || address_ != address) {
client_pool_ =
ClientPool::create(address, config_, io_context_pool_);
address_ = address;
std::string addr(address);
auto it = pools_.find(addr);
if (it == pools_.end()) {
auto pool = ClientPool::create(addr, config_, io_context_pool_);
it = pools_.emplace(addr, std::move(pool)).first;
}
address_ = std::move(addr);
client_pool_ = it->second;
return client_pool_;
}

Expand All @@ -58,12 +64,21 @@ class RpcClientPool {
return client_pool_;
}

std::string GetAddress() const {
std::shared_lock<std::shared_mutex> lock(mutex_);
return address_;
}

private:
mutable std::shared_mutex mutex_;
coro_io::io_context_pool& io_context_pool_;
PoolConfig config_;
std::string address_;
std::shared_ptr<ClientPool> client_pool_;
// Cache of client pools keyed by target address, so switching back and
// forth between submaster addresses reuses existing connections instead of
// recreating the pool on every switch.
std::unordered_map<std::string, std::shared_ptr<ClientPool>> pools_;
};

} // namespace mooncake
9 changes: 5 additions & 4 deletions mooncake-common/tests/rpc_client_io_context_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,19 @@ TEST(RpcClientIoContextPoolTest, UsesConfiguredSizeAndReusesPool) {
EXPECT_NE(&first_pool, &second_pool);
}

TEST(RpcClientIoContextPoolTest, ReplacesPoolWhenTargetChanges) {
TEST(RpcClientIoContextPoolTest, CachesPoolsPerAddress) {
RpcClientPool pools(GetFirstTestRpcClientIoContextPool());

auto first = pools.GetOrCreateClientPool("127.0.0.1:10001");
std::weak_ptr<RpcClientPool::ClientPool> old_pool = first;
EXPECT_EQ(pools.GetOrCreateClientPool("127.0.0.1:10001"), first);

auto second = pools.GetOrCreateClientPool("127.0.0.1:10002");
EXPECT_NE(first, second);
first.reset();
EXPECT_TRUE(old_pool.expired());
EXPECT_EQ(pools.GetClientPool(), second);

// Switching back reuses the cached pool instead of recreating it.
EXPECT_EQ(pools.GetOrCreateClientPool("127.0.0.1:10001"), first);
EXPECT_EQ(pools.GetClientPool(), first);
}

TEST(RpcClientIoContextPoolTest, SendsToNewAddressAfterSwitch) {
Expand Down
14 changes: 14 additions & 0 deletions mooncake-store/benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ target_link_libraries(
stress_cluster_bench PRIVATE mooncake_store transfer_engine asio_shared
gflags::gflags glog::glog pthread)

# CFM client benchmark. Simulates vLLM inference requests as KV-cache block
# accesses and reports both client performance and IO Pattern observability.
add_executable(cfm_client_bench cfm_client_bench.cpp)
target_link_libraries(
cfm_client_bench PRIVATE mooncake_store transfer_engine asio_shared
gflags::gflags glog::glog pthread)

# Benchmark for vLLM Store Connector path
# Triggers: batch_put_from_multi_buffers / batchIsExist /
# batch_get_into_multi_buffers (and setup/register_buffer/tearDownAll).
Expand Down Expand Up @@ -75,3 +82,10 @@ if(STORE_USE_ETCD)
oplog_batch_bench PRIVATE mooncake_store glog::glog gflags::gflags
JsonCpp::JsonCpp)
endif()

if(STORE_USE_ETCD)
add_executable(vchunk_distributed_bench vchunk_distributed_bench.cpp)
target_link_libraries(
vchunk_distributed_bench PRIVATE mooncake_store transfer_engine asio_shared
gflags::gflags glog::glog pthread)
endif()
Loading
Loading