Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 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
1d89e5e
修复cfm client问题
Gzure Sep 8, 2026
15e1ee9
修复cfm client问题
Gzure Sep 8, 2026
fed6d9e
修复cfm client问题
Gzure Sep 8, 2026
89293b4
修复cfm client问题1
Gzure Sep 8, 2026
17d2074
修复cfm client问题1
Gzure Sep 8, 2026
2db825c
修复cfm client问题2
Gzure Sep 9, 2026
bf762ed
修复cfm client问题3
Gzure Sep 9, 2026
af203fa
修复cfm client问题4
Gzure Sep 9, 2026
92b6485
修复cfm client问题5
Gzure Sep 9, 2026
d33fd00
修复cfm client问题6
Gzure Sep 9, 2026
18bf223
修复cfm client问题7
Gzure Sep 9, 2026
6985a19
修复cfm client问题8
Gzure Sep 9, 2026
999b128
修复io_pattern问题1
Gzure Sep 10, 2026
c11bc6d
io_pattern修复1
Gzure Sep 10, 2026
8b55fae
io_pattern修复2
Gzure Sep 10, 2026
00dd4fa
io_pattern修复3
Gzure Sep 10, 2026
818560a
io_pattern修复3
Gzure Sep 10, 2026
68390b6
io_pattern修复3
Gzure Sep 10, 2026
2dc7f4b
io_pattern修复3
Gzure Sep 10, 2026
33ed27d
io_pattern修复3
Gzure Sep 10, 2026
9625374
io_pattern修复3
Gzure Sep 10, 2026
f139a03
io_pattern修复4
Gzure Sep 10, 2026
8a50189
io_pattern修复5
Gzure Sep 10, 2026
813c038
io_pattern修复5
Gzure Sep 10, 2026
87c759c
io_pattern修复5
Gzure Sep 10, 2026
95c4fd0
io_pattern修复6
Gzure Sep 10, 2026
2ae5da4
io_pattern修复6
Gzure Sep 10, 2026
7569327
io_pattern修复6
Gzure Sep 10, 2026
324c31c
io_pattern修复7
Gzure Sep 10, 2026
4264679
io_pattern修复7
Gzure Sep 10, 2026
f67aeae
io_pattern修复8
Gzure Sep 10, 2026
4bc5fe3
add io_pattern metric
Gzure Sep 14, 2026
090cc12
add io_pattern metric
Gzure Sep 14, 2026
cfc5319
add io_pattern metric
Gzure Sep 14, 2026
987b07e
add io_pattern metric
Gzure Sep 14, 2026
3ab266a
add io_pattern metric
Gzure Sep 14, 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,284 changes: 1,284 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
17 changes: 17 additions & 0 deletions mooncake-store/benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ 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)
if(STORE_USE_ETCD)
target_link_libraries(cfm_client_bench PRIVATE ${ETCD_WRAPPER_LIB})
endif()

# 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 +85,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