Skip to content

Commit 8d494bd

Browse files
excelle08meta-codesync[bot]
authored andcommitted
Wire LeafNodeRank to mock_services for outbound RPC fanout (#723)
Summary: Pull Request resolved: #723 Phase 5 closes the loop on the prod-shaped RPC stack: LeafNodeRank now issues real outbound Thrift RPCs to the mock_services server stood up in 5/1, replacing the synthetic `folly::futures::sleep(io_latency_ms)` callsites in the request handlers. This is the change that actually puts the RPC stack on-CPU during a request, which is what the multifeed_aggregator profile spends most of its time in. # Generalize percentile sampling: PercentileSampler + RpcDistRegistry `RequestSizeSampler` was hard-coded to one prefixed distribution per JSON file. We now need 60 distributions (20 outbound methods x {request_size, response_size, latency_us}). `PercentileSampler.h` is the generalized inverse-CDF sampler: - `load(path, prefix)` keeps the legacy prefixed-keys shape used by DriverNodeRank's `--request_size_distribution` flag. - `loadFromDynamic(obj)` accepts a bare `{min,p05,...,max}` object — the shape used by every per-method sub-object in `rpc_dist.json`. - `sample(rng)` and `sampleI64(rng)` cover both size and latency distributions. `RequestSizeSampler.h` is now a one-line `using` alias so DriverNodeRank keeps building unmodified. `RpcDistRegistry.h` loads `rpc_dist.json` once at startup and exposes the 60 outbound samplers via either `MethodIdx` enum or string-keyed accessor. The `kPerSessionCounts` table is hard-coded from the researcher notes (not parsed from the JSON) so a missing or stale `rpc_dist.json` cannot silently change the fanout calibration. See ~/feedsim_v2/docs/phase5_researcher_notes.md §4 for the per-method numbers. # Per-thread Thrift client: MockServicesClient `MockServicesClient` wraps the generated `MockServiceAsyncClient` with a compile-time switch over `MethodIdx`. We deliberately use the named `semifuture_<method>()` calls rather than a single dynamic-name dispatch — preserving distinct `AsyncClient::send_<method>` symbols in Strobelight, which is the entire reason `MockService.thrift` declares 20 methods rather than one generic `call()`. Thread-safety strategy: one client per LeafNodeRank worker thread, each pinned to one EventBase from the SREventBase pool (the outbound-EventBase pool added in Phase 4). `MockServicesClient`'s constructor and destructor both `runInEventBaseThreadAndWait` to keep the AsyncClient + RocketClientChannel on their owning EventBase thread. Wire contract (matches what mock_services from 5/1 expects): the first 4 bytes of the request body are a big-endian `uint32_t response_size`. The server reads that header and sizes its response accordingly, so client and server stay in sync without an out-of-band agreement. # Fanout integration in LeafNodeRank Three new CLI flags: - `--rpc_dist_path`: path to `rpc_dist.json`. Default empty — when unset, the legacy `folly::futures::sleep` path is preserved verbatim (regression-safety A/B comparison). - `--mock_services_host` / `--mock_services_port`: target (defaults `127.0.0.1:21222`). - `--rpc_fanout_scale`: scale factor on per-session counts. Default `0.025` yields ~94 RPCs per inbound session (vs ~3742 at scale=1.0); the table in §4 of the researcher notes documents the calibration tradeoff. `issueOutboundFanout(td, scale)` iterates the 20 methods, computes `n = max(1, round(per_session_count * scale))` for each, samples request size / response size / latency from the registry, builds a request body (4-byte BE header + Silesia bytes if available, else zero-filled padding), and dispatches via the per-thread `MockServicesClient`. The Future<int> resolves once `folly::collectAll` of all per-call futures completes. `simulateIoOrFanout(td, ...)` is the drop-in replacement for `folly::futures::sleep`. When `td.mock_client` is non-null (i.e. `--rpc_dist_path` was set), it fans out; otherwise it sleeps. The three callsites that get this treatment are the I/O simulation in `AsyncPageRankRequestHandler`, `DLRMRequestHandler`, and the legacy sync `PageRankRequestHandler`. The 1ms inter-stage breather around line 1735 is intentionally left as `folly::futures::sleep` per the researcher notes — that's not modeled I/O. ThreadStartup populates `td.rpc_registry`, `td.rpc_silesia`, `td.mock_client`, and a per-thread `std::mt19937 rpc_rng`. If the connection to mock_services fails at startup, the code logs and falls back to the legacy sleep path for that thread rather than aborting (defensive — a handful of slow startups shouldn't take down the whole benchmark, and the warning will surface in install logs). # Build wiring CMake: `LeafNodeRank` now compiles `MockServicesClient.cc` and links `MockService-cpp2`. Added the corresponding `add_dependencies(LeafNodeRank MockService-cpp2-target)` so the thrift bindings are generated before LeafNodeRank starts compiling. `MockServicesClient.cc` includes `mock_services/gen-cpp2/MockServiceAsyncClient.h` directly; the existing `${CMAKE_CURRENT_SOURCE_DIR}` include path makes that visible. # Test calibration 20 methods × scale=0.025 = exactly **94 calls per session** (matches the researcher table — verified independently by recomputing the ceil/round). Per-method breakdown is in researcher notes §4. Reviewed By: charles-typ Differential Revision: D103772853
1 parent 04fef7e commit 8d494bd

14 files changed

Lines changed: 3262 additions & 166 deletions

packages/feedsim/install_feedsim.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ chmod u+x "${FEEDSIM_ROOT_SRC}/run-feedsim-multi.sh"
6161
# Copy production size distribution JSONs (consumed by run.sh / DriverNodeRank).
6262
cp "${BENCHPRESS_ROOT}/packages/feedsim/feed_aggregator_req_sizes.json" "${FEEDSIM_ROOT_SRC}/feed_aggregator_req_sizes.json"
6363
cp "${BENCHPRESS_ROOT}/packages/feedsim/feed_aggregator_resp_sizes.json" "${FEEDSIM_ROOT_SRC}/feed_aggregator_resp_sizes.json"
64+
# Phase 6 session-mode driver loads rpc_dist.json from the FEEDSIM_ROOT runtime dir.
65+
cp "${BENCHPRESS_ROOT}/packages/feedsim/rpc_dist.json" "${FEEDSIM_ROOT_SRC}/rpc_dist.json"
6466

6567
msg "Installing third-party dependencies..."
6668
cp -r "${BENCHPRESS_ROOT}/packages/feedsim/third_party" "${FEEDSIM_ROOT_SRC}"

packages/feedsim/install_feedsim_aarch64.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ chmod u+x "${FEEDSIM_ROOT_SRC}/run-feedsim-multi.sh"
6767
# Copy production size distribution JSONs (consumed by run.sh / DriverNodeRank).
6868
cp "${BENCHPRESS_ROOT}/packages/feedsim/feed_aggregator_req_sizes.json" "${FEEDSIM_ROOT_SRC}/feed_aggregator_req_sizes.json"
6969
cp "${BENCHPRESS_ROOT}/packages/feedsim/feed_aggregator_resp_sizes.json" "${FEEDSIM_ROOT_SRC}/feed_aggregator_resp_sizes.json"
70+
# Phase 6 session-mode driver loads rpc_dist.json from the FEEDSIM_ROOT runtime dir.
71+
cp "${BENCHPRESS_ROOT}/packages/feedsim/rpc_dist.json" "${FEEDSIM_ROOT_SRC}/rpc_dist.json"
7072

7173
msg "Installing third-party dependencies..."
7274
mkdir -p "${FEEDSIM_THIRD_PARTY_SRC}"

0 commit comments

Comments
 (0)