perf: send one AppendEntries RPC per matching-point probe - #2077
Conversation
|
I am reopening this PR. As commented in #2073 (comment), changing size to 8 can cause regression to other users and it makes the binary search within small gap slower. Even with #2076, we would still need binary search so this optimization would still help. |
|
Thank you, @zhixinwen, for identifying this issue, implementing the optimization, and asking us to help refine it. The core idea remains unchanged: once a probe sends an entry-carrying request, its response contains enough information to choose the next midpoint. Sending the rest of the candidate range only delays matching-point discovery. We made a follow-up refactor on
This preserves the optimization while making the probe lifecycle and retry rules more explicit. |
85bb762 to
b56c513
Compare
drmingdrmer
left a comment
There was a problem hiding this comment.
@drmingdrmer reviewed 23 files and all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on zhixinwen).
b56c513 to
f078e1b
Compare
drmingdrmer
left a comment
There was a problem hiding this comment.
@drmingdrmer reviewed 5 files and all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on zhixinwen).
# Summary Stop a matching-point probe after its first entry-carrying AppendEntries request. A storage byte limit can no longer split one probe into several entry-carrying RPCs before the next midpoint is chosen. # Details Model bounded probes explicitly in `Payload` and `Inflight`, separate from open-ended log streaming. Keep probe behavior out of `LogIdRange` and let each payload update return only the work left to send: `run_stream_session()` returns the remaining payload and `ReplicationCore::main()` stores it as the next action. Complete a probe when a response acknowledges `prev` or a later log. Track acknowledgements as `Option<Option<LogId>>` so no response stays distinct from an acknowledgement of the empty log position, and forward `Ok(None)` to RaftCore so a probe that starts at `None` completes. A storage read that returns no entry still sends the request with `prev` and no entries; the engine's probe completes when the follower acknowledges `prev`. An empty probe still sends one commit-only request. RPC and conflict interruptions leave rescheduling to RaftCore. The integration test `t11_probe_partial_success_without_entry` records the `prev_log_id` of the first two entry-carrying probes to each follower: with 40 writes they are index 15 and then 23, where the previous code retried index 15; with 8 writes both are `None`.
f078e1b to
e33ae93
Compare
drmingdrmer
left a comment
There was a problem hiding this comment.
@drmingdrmer reviewed 5 files and all commit messages.
Reviewable status:complete! all files reviewed, all discussions resolved (waiting on zhixinwen).
Matching-point discovery drains every storage-limited chunk of a probe range before choosing the next midpoint. For example, a 500-entry probe split into ten storage reads can require ten RPCs even though the first response provides enough information to continue discovery.
This change sends one entry-carrying AppendEntries request per probe. Storage may return a prefix of the candidate range; once the follower acknowledges an entry beyond
prev, the engine finishes the probe and recomputes the next midpoint. The existingmax_payload_entriescap still applies.The engine reuses
Inflight::Logs: both probes and the leader's local progress update complete on the first acknowledgement beyondprev(the local update acknowledges the entire range immediately).Payload::Probegives the replication task the probe-specific sending and retry rules, separate from commit-only appends. Completion is handled centrally byPayload::update_matching(), sonext_requestneeds no probe-specific branch. Pipeline replication is unchanged, and all changed types are internal.The engine and replication task share
LogIdRange::probe_completed_by().PartialSuccess(prev)verifiesprevbut acknowledges no additional entry, so the same probe is retried. A session with no response also leaves it pending. This decision uses the current session's maximum acknowledgement, sinceremote_matchedcan contain progress from earlier sessions. Keeping the maximum prevents a later, lower response from undoing the session's completion decision.Tests cover:
(52, 60]: the request stream ends without reading or sending the suffix. An initial empty storage read leaves the probe pending.prev = None) remaining pending without an acknowledgement and completing when the first entry is acknowledged.A transport closing its response stream without answering is not directly covered by a network mock.
Validation: formatting and all three workspace Clippy configurations pass.
make verifyencounters a local C++ standard-header error while building the unchanged RocksDB example.make -o fmt_check -o clippy verifypasses documentation checks, library tests, integration tests, and the remaining macro checks.This change is