Skip to content

Make reply capture opt-in (--capture-replies) so it doesn't inflate query latency - #123

Merged
fcostaoliveira merged 1 commit into
masterfrom
fix/optin-reply-capture-117
Jul 13, 2026
Merged

Make reply capture opt-in (--capture-replies) so it doesn't inflate query latency#123
fcostaoliveira merged 1 commit into
masterfrom
fix/optin-reply-capture-117

Conversation

@fcostaoliveira

Copy link
Copy Markdown
Contributor

Closes #117.

Problem

#114 changed the per-command receiver from a discarded nil interface{} to new(interface{}) so RxBytes could be populated. But a *interface{} receiver makes radix fully unmarshal every RESP reply into nested Go values via reflection — inside client.Do, i.e. inside the measured latency window. For FT.SEARCH / FT.AGGREGATE (O(docs × fields) allocations per query) this materially inflates the very read/vector latencies these benchmarks exist to measure, and no RediSearch benchmark spec consumes RxBytes.

Fix

Make reply capture opt-in via --capture-replies (default false):

  • default (off): the receiver is a nil interface again, so radix reads-and-discards the reply with no allocation and no reflection — latency fidelity restored. RxBytes is 0.
  • --capture-replies: replies are decoded and getRxLen populates RxBytes.

Command errors are surfaced by radix regardless of the receiver, so error accounting is unaffected either way.

Validation

E2E (2000 HSET):

TxBytes RxBytes
default 49780 0
--capture-replies 49780 2000

TxBytes (sent-byte accounting) is identical both ways. Adds TestFTSBCaptureRepliesControlsRxBytes (asserts the flag flips RxBytes 0↔>0) and updates the pipeline-tail test to the new default. Unit + integration suites green (-race).

)

#114 changed the per-command receiver from a discarded nil interface to
new(interface{}) so RxBytes could be populated. But that fully unmarshals every
RESP reply into nested Go values via reflection INSIDE client.Do -- i.e. inside
the measured latency window. For FT.SEARCH / FT.AGGREGATE (O(docs*fields)
allocations per query) this materially inflates the very read/vector latencies
these benchmarks exist to measure, and RxBytes has no consumer in the specs.

Make capture opt-in via --capture-replies (default false): the receiver is a nil
interface again, so radix reads-and-discards the reply with no allocation or
reflection -- restoring latency fidelity by default. With the flag on, replies
are decoded and getRxLen populates RxBytes. Command errors are surfaced by radix
regardless of the receiver, so error accounting is unaffected either way.

Validated E2E: default run -> RxBytes=0, TxBytes unchanged; --capture-replies ->
RxBytes>0, same TxBytes. Adds TestFTSBCaptureRepliesControlsRxBytes and updates
the pipeline-tail test to the new default.
@sonarqubecloud

Copy link
Copy Markdown

@fcostaoliveira
fcostaoliveira merged commit a1a7f68 into master Jul 13, 2026
3 checks passed
@fcostaoliveira
fcostaoliveira deleted the fix/optin-reply-capture-117 branch July 13, 2026 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ftsb_redisearch: reply capture (#114) unmarshals full RESP reply inside the measured latency window (inflates FT.SEARCH latency)

1 participant