Skip to content

Benchmark transaction-submission latency #869

Closed

Description

@marwen-abid

Metric definition

Time for RPC to serve a transaction submission: receive the HTTP call, proxy to core's submit endpoint, parse and return the result.

This is measurable today: the v2 submission path is essentially the v1 path.

Scope

  • Measure submission latency across the three transaction profiles, which differ in XDR size (SAC ≈ 1 KB, contract-token/OZ ≈ 1 KB, Soroswap ≈ 2×) — size affects encode/decode if that ever becomes a factor.
  • Report p50/p99 per profile, with the measurement setup documented (client location, network assumptions — the org-wide assumption is 50 ms client↔RPC RTT, which must be excluded or stated).
  • Document the methodology alongside the number.

Done when

We have reproducible per-profile numbers with a documented method.

Activity

  1. Shaptic commented on Jul 17, 2026

    @Shaptic
    Contributor

    Just for context and an initial ballpark, when I analyze the vegeta-provided latency of the mainnet TPS load test (running on an m6id.4xlarge), I see the following:

    Round-trip time of POST /transactions to receiving PENDING, including network latency:

    Workload Mean
    SAC 67ms
    OZ 59ms
    Soroswap 55ms

    I know this isn't enough to consider this "done," but it is a known starting point with v1 that we can point to for hand-waving if necessary. We should expect the same results, if not better given that network latency isn't part of this metric, with v2 once that's all wired in given that the submission code and execution path should be nearly identical.

  2. self-assigned this
    on Jul 21, 2026
  3. moved this from To Do to In Progress in Platform Scrumon Jul 24, 2026
  4. marwen-abid commented on Jul 28, 2026

    @marwen-abid
    ContributorAuthor

    Results: transaction-submission latency measured inside RPC

    Method. The p99 60 ms submission target decomposes into ~50 ms client↔RPC network RTT plus <10 ms inside the RPC process, so this benchmark measures the in-RPC part and treats the RTT as a constant. Two existing instruments cover it — no new code:

    • finished JSONRPC request log line — full sendTransaction handler duration, one line per request (joined to the starting JSONRPC request line on req to filter by method). This is the headline distribution.
    • soroban_rpc_txsub_submission_duration_seconds — the synchronous RPC→Core POST /tx leg alone.
    • RPC residue (XDR decode, hash, JSONify) = handler mean − core-leg mean. Means only; quantiles do not subtract.

    Environment. stellar/quickstart:testing (stellar-rpc v27.1.1) on an m6id.2xlarge. Load = real fee-bumped Soroban transactions from the tx-load-test tool in stellar-rpc-blaster, three profiles: SAC transfer (≈1 KB), OpenZeppelin token transfer (≈1 KB), Soroswap router swap (≈2.6 KB). Standalone network: 10 RPS × 120 s per profile (~1,150 samples each). Testnet: same box, 2 RPS × 60 s (~115 samples each). Every submission was accepted (PENDING); zero poll errors in every run.

    Standalone (headline):

    Profile n p50 p90 p99 max core-leg mean RPC residue mean
    SAC transfer 1155 1.14 ms 1.30 ms 4.36 ms 11.4 ms 1.03 ms 0.20 ms
    OZ transfer 1154 1.10 ms 1.25 ms 3.08 ms 15.4 ms 0.99 ms 0.20 ms
    Soroswap swap 1152 1.22 ms 1.39 ms 4.56 ms 13.3 ms 1.07 ms 0.25 ms

    Testnet (confirmation):

    Profile n p50 p90 p99 max core-leg mean RPC residue mean
    SAC transfer 114 1.16 ms 1.30 ms 4.00 ms 9.2 ms 1.08 ms 0.19 ms
    OZ transfer 115 1.12 ms 1.28 ms 1.43 ms 7.5 ms 0.99 ms 0.20 ms
    Soroswap swap 114 1.19 ms 1.39 ms 1.99 ms 12.6 ms 1.08 ms 0.24 ms

    Findings.

    1. Worst-profile p99 is 4.6 ms — the <10 ms in-RPC slice holds with 2× headroom. Total slice estimate: 50 + 4.6 ≈ 55 ms against the 60 ms target.
    2. The RPC→Core call carries ~80–83 % of the mean and drives the tail (core-leg p99 tracks handler p99 in every profile). RPC's own processing is ~0.2 ms, flat across profiles.
    3. Envelope size barely matters: the ≈2.6 KB Soroswap profile adds ~0.1 ms at p50 over the ≈1 KB profiles.
    4. Standalone ≈ testnet: medians agree within ~2 %, core-leg means within 5 % — the measured path (handler + local core admission) never touches the network. The thinner testnet p99s are sample-size noise at n≈114.
    5. Cross-checks: log-derived means match the soroban_rpc_json_rpc_request_duration_seconds Summary exactly, counts agree across logs, metrics, and the client, and client-observed HTTP RTT (p50 ≈ 2.5 ms) = handler time + the localhost/nginx hop.

    Reproduce. Runner + log-harvest scripts: scripts/tx-submission/ in stellar-rpc-blaster (branch tx-submission-harvest). Raw bundles (client NDJSON, RPC log slices, /metrics scrapes, per-profile summary JSONs): gs://rpc-full-history/results/txsub-standalone-20260728/ and gs://rpc-full-history/results/txsub-testnet-20260728/.

    Measured on v1 (v27.1.1); the v2 submission path is expected to be equivalent — re-verify when it is final.

  5. marwen-abid commented on Jul 28, 2026

    @marwen-abid
    ContributorAuthor
  6. moved this from In Progress to Needs Review in Platform Scrumon Jul 28, 2026
  7. moved this from Needs Review to Done in Platform Scrumon Jul 30, 2026
  8. closed this as completedby moving to Done in Platform Scrumon Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions