Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
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
3aa69a8
add io_pattern metric
Gzure Sep 14, 2026
85c1f14
add io_pattern metric
Gzure Sep 14, 2026
d4b3c53
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.

10 changes: 10 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
1,517 changes: 1,517 additions & 0 deletions mooncake-store/benchmarks/cfm_client_bench.cpp

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions mooncake-store/graphify-out/cache/stat-index.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions mooncake-store/include/admission_ops.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

#include "io_pattern/ops.h"
3 changes: 3 additions & 0 deletions mooncake-store/include/cfm_client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

#include "io_pattern/client.h"
2 changes: 2 additions & 0 deletions mooncake-store/include/cfm_client_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#pragma once
#include "io_pattern/cfm_client_impl.h"
2 changes: 2 additions & 0 deletions mooncake-store/include/collector_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#pragma once
#include "io_pattern/collector_impl.h"
2 changes: 2 additions & 0 deletions mooncake-store/include/degrading_policy_engine.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#pragma once
#include "io_pattern/degrading_policy_engine.h"
3 changes: 3 additions & 0 deletions mooncake-store/include/eviction_ops.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

#include "io_pattern/ops.h"
2 changes: 2 additions & 0 deletions mooncake-store/include/feedback.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#pragma once
#include "io_pattern/feedback.h"
3 changes: 3 additions & 0 deletions mooncake-store/include/io_pattern.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

#include "io_pattern/io_pattern.h"
19 changes: 19 additions & 0 deletions mooncake-store/include/io_pattern/analyzer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include "io_pattern/types.h"

namespace mooncake::io_pattern {

// Converts an immutable snapshot into workload and per-object features.
class IoPatternAnalyzer {
public:
virtual ~IoPatternAnalyzer() = default;

virtual PatternResult Analyze(const IoPatternSnapshot& snapshot) const = 0;
virtual WorkloadType DetectWorkloadType(
const IoPatternSnapshot& snapshot) const = 0;
virtual float CalculateConfidence(
const ObjectRef& object, const IoPatternSnapshot& snapshot) const = 0;
};

} // namespace mooncake::io_pattern
26 changes: 26 additions & 0 deletions mooncake-store/include/io_pattern/cfm_channel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include <optional>
#include <utility>

#include "reporter.h"
#include "types.h"
#include "../types.h"

namespace mooncake::io_pattern {

// Transport-neutral CFM reporting channel. In the embedded architecture a
// SubMaster owns CFM for the keys in its slots, so a channel delivers reports
// (snapshots and metric batches) and explicit prefetch plans to the owning
// SubMaster endpoint. There is no policy polling or delivery acknowledgement
// loop: the receiver merges reports into its local runtime and policy
// commands execute on the SubMaster that owns the reported keys.
class CfmChannel {
public:
virtual ~CfmChannel() = default;
virtual bool SendSnapshot(const IoPatternSnapshot& snapshot) = 0;
virtual bool SendMetricBatch(const MetricBatch& batch) = 0;
virtual ErrorCode ExecutePrefetch(const PrefetchPlan& plan) = 0;
};

} // namespace mooncake::io_pattern
28 changes: 28 additions & 0 deletions mooncake-store/include/io_pattern/cfm_client_impl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

#include <memory>
#include <utility>

#include "cfm_channel.h"
#include "client.h"

namespace mooncake::io_pattern {

// Reporting client used by inference-side connectors and integration tests.
// Network behavior is delegated to the injected channel; the client is what a
// vLLM/SGLang connector sees when it reports IO Pattern observations for keys
// owned by the addressed SubMaster.
class CfmClientImpl final : public CfmClient {
public:
explicit CfmClientImpl(std::shared_ptr<CfmChannel> channel)
: channel_(std::move(channel)) {}

ErrorCode ReportSnapshot(const IoPatternSnapshot& snapshot) override;
ErrorCode ReportMetricBatch(const MetricBatch& batch) override;
ErrorCode ExecutePrefetch(const PrefetchPlan& plan) override;

private:
std::shared_ptr<CfmChannel> channel_;
};

} // namespace mooncake::io_pattern
28 changes: 28 additions & 0 deletions mooncake-store/include/io_pattern/cfm_ingress.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

#include <memory>
#include <string_view>

#include "cfm_protocol.h"
#include "runtime.h"

namespace mooncake::io_pattern {

// Server-side counterpart of CfmRpcChannel. Bind Handle() as an
// InProcessCfmRpcTransport::SendHandler or adapt it to a network RPC server.
class CfmIngress final {
public:
explicit CfmIngress(std::shared_ptr<IoPatternRuntime> runtime,
std::shared_ptr<CfmBinaryCodec> codec =
std::make_shared<CfmBinaryCodec>())
: runtime_(std::move(runtime)), codec_(std::move(codec)) {}

bool Handle(std::string_view method, std::string_view payload,
std::string_view source_id = {});

private:
std::shared_ptr<IoPatternRuntime> runtime_;
std::shared_ptr<CfmBinaryCodec> codec_;
};

} // namespace mooncake::io_pattern
83 changes: 83 additions & 0 deletions mooncake-store/include/io_pattern/cfm_ownership_client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#pragma once

#include <atomic>
#include <chrono>
#include <functional>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>

#include "client.h"
#include "cfm_channel.h"
#include "cfm_protocol.h"
#include "cfm_service.h"
#include "reporter.h"
#include "rpc_transport.h"
#include "types.h"

namespace mooncake::io_pattern {

// Resolves the SubMaster that owns a reported object. Production callers feed
// this from the CVM key->slot->submaster mapping (cvm::KeySlot over the etcd
// /cvm/<ns> master registry) inside the Store client / connector layer;
// returns the SubMaster's regular coro_rpc endpoint ("host:port"), the same
// endpoint every other Mooncake RPC of that SubMaster uses.
using SubmasterEndpointResolver =
std::function<std::optional<std::string>(const TenantId&, const std::string&)>;

// Ownership-addressed CFM reporting client.
//
// CFM is a component of every SubMaster; there is no standalone CFM Master
// and no auth token. A caller (inference connector / Store client) observes
// keys that may live on many SubMasters, so reports are bucketed by the CVM
// ownership resolver: observations whose key belongs to the same SubMaster are
// aggregated into one metric batch and delivered to that SubMaster's embedded
// CFM over its ordinary coro_rpc endpoint. Metrics whose owner cannot be
// resolved are dropped and counted so callers can degrade instead of guessing.
class CfmOwnershipClient final : public CfmClient {
public:
// `resolver` maps a reported object to the owning SubMaster endpoint. It
// must be kept up to date with the CVM route (slot rebalance is rare).
// `timeout` applies to every RPC.
explicit CfmOwnershipClient(SubmasterEndpointResolver resolver,
std::chrono::milliseconds timeout =
std::chrono::milliseconds(500));

// Sends the snapshot, grouped by the owning SubMaster of each key.
ErrorCode ReportSnapshot(const IoPatternSnapshot& snapshot) override;

// Sends the metric batch, grouped by the owning SubMaster of each
// inference/access object. Storage observations are deliberately not
// routed by default: the SubMaster that owns the underlying storage
// already reports its own watermark to its local runtime. Benchmark /
// simulation callers can enable forward_storage to have the storage
// metrics ride along with each owner-addressed report so a remote run can
// drive the report-driven eviction dimension.
ErrorCode ReportMetricBatch(const MetricBatch& batch) override;

void set_forward_storage(bool forward) { forward_storage_ = forward; }

// Sends an explicit prefetch plan to the SubMaster that owns the first
// candidate; that SubMaster executes it through its local storage-safe
// handlers.
ErrorCode ExecutePrefetch(const PrefetchPlan& plan) override;

// Observations dropped because no owner could be resolved.
uint64_t dropped_observations() const;

private:
std::shared_ptr<CfmChannel> ChannelFor(const std::string& endpoint);
std::string OwnerEndpoint(const ObjectRef& object) const;

SubmasterEndpointResolver resolver_;
std::chrono::milliseconds timeout_;
std::unordered_map<std::string, std::shared_ptr<CfmChannel>> channels_;
mutable std::mutex channels_mutex_;
std::atomic<uint64_t> dropped_observations_{0};
bool forward_storage_{false};
};

} // namespace mooncake::io_pattern
22 changes: 22 additions & 0 deletions mooncake-store/include/io_pattern/cfm_protocol.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "rpc_transport.h"

namespace mooncake::io_pattern {

// Versioned binary wire codec for the CFM RPC methods. It deliberately owns
// every serialization detail so transports only deal in method/payload bytes.
class CfmBinaryCodec final : public CfmRpcCodec {
public:
std::string EncodeSnapshot(const IoPatternSnapshot& snapshot) const override;
std::string EncodePrefetch(const PrefetchPlan& plan) const override;
std::string EncodeMetricBatch(const MetricBatch& batch) const override;
std::optional<PolicyCommand> DecodePolicy(const std::string& payload) const override;

std::optional<IoPatternSnapshot> DecodeSnapshot(
const std::string& payload) const;
std::optional<MetricBatch> DecodeMetricBatch(const std::string& payload) const;
std::string EncodePolicy(const PolicyCommand& command) const;
};

} // namespace mooncake::io_pattern
67 changes: 67 additions & 0 deletions mooncake-store/include/io_pattern/cfm_service.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#pragma once

#include <chrono>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <utility>

#include "cfm_ingress.h"
#include "observability.h"
#include "types.h"

namespace mooncake::io_pattern {

// Embedded CFM endpoint of one SubMaster. There is no standalone CFM Master:
// every SubMaster runs the full IO Pattern pipeline locally and accepts
// ownership-addressed metric reports over its regular coro_rpc port (the same
// endpoint the rest of Mooncake uses). Received batches are merged straight
// into the local runtime so collection, analysis and policy execution all stay
// on the SubMaster that owns the reported keys.
//
// Reports are addressed by key ownership, so a receiving SubMaster only ever
// merges observations for keys that belong to its own slots. A separate node
// identity, delivery queues and a poll/ack loop are therefore unnecessary: the
// reporting client fans each batch out to the owning SubMaster(s) using the
// CVM key->slot->submaster mapping.
class CfmService final {
public:
explicit CfmService(std::shared_ptr<IoPatternRuntime> runtime);

// RPC entry point. Supported methods:
// report_metric_batch / report_snapshot -> merge into the local runtime
// execute_prefetch / execute_policy -> execute through the local
// runtime's storage handlers
// `source_id` identifies the reporting process and is used to normalize
// remote StorageMetric watermarks.
bool Send(std::string_view method, std::string_view payload,
std::string_view source_id = {});

IoPatternSnapshot Snapshot() const;
IoPatternObservabilitySnapshot Observability(
double window_seconds = 0.0) const;

private:
std::shared_ptr<IoPatternRuntime> runtime_;
std::shared_ptr<CfmBinaryCodec> codec_;
CfmIngress ingress_;
};

// coro_rpc-facing adapter. Keeping the RPC signature here lets both the
// SubMaster server and integration tests register the exact production
// endpoint.
class CfmRpcService final {
public:
explicit CfmRpcService(std::shared_ptr<CfmService> service)
: service_(std::move(service)) {}

bool Send(const std::string& method, const std::string& payload,
const std::string& source_id = {});

private:
std::shared_ptr<CfmService> service_;
};

} // namespace mooncake::io_pattern
22 changes: 22 additions & 0 deletions mooncake-store/include/io_pattern/client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "../types.h"
#include "reporter.h"
#include "types.h"

namespace mooncake::io_pattern {

// Adapter seam between an inference node and the Cache Flow Manager of the
// SubMaster(s) that own the reported keys. Reports are sent over the same
// coro_rpc endpoint every other Mooncake API uses; there is no separate CFM
// Master and no credential to obtain.
class CfmClient {
public:
virtual ~CfmClient() = default;

virtual ErrorCode ReportSnapshot(const IoPatternSnapshot& snapshot) = 0;
virtual ErrorCode ReportMetricBatch(const MetricBatch& batch) = 0;
virtual ErrorCode ExecutePrefetch(const PrefetchPlan& plan) = 0;
};

} // namespace mooncake::io_pattern
20 changes: 20 additions & 0 deletions mooncake-store/include/io_pattern/collector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include "io_pattern/types.h"

namespace mooncake::io_pattern {

// Collects non-blocking, already-aggregated observations from data paths.
class IoPatternCollector {
public:
virtual ~IoPatternCollector() = default;

// Implementations must not block the caller on RPC or storage I/O.
virtual void ReportInferenceMetrics(const InferenceMetrics& metrics) = 0;
virtual void RecordAccess(const std::string& key,
const AccessRecord& record) = 0;
virtual void RecordStorageMetric(const StorageMetric& metric) = 0;
virtual IoPatternSnapshot GetSnapshot() const = 0;
};

} // namespace mooncake::io_pattern
Loading
Loading