Skip to content

Make Soroban metric batching code lock-free. - #5436

Open
dmkozh wants to merge 1 commit into
stellar:masterfrom
dmkozh:apply_metrics_no_sync
Open

Make Soroban metric batching code lock-free.#5436
dmkozh wants to merge 1 commit into
stellar:masterfrom
dmkozh:apply_metrics_no_sync

Conversation

@dmkozh

@dmkozh dmkozh commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Description

The previous attempt at batching Soroban metrics still had some locks and was overall more convoluted than it needs to be. With this change we simply give every thread its own metrics batch to write to, and then cleanly move the batches to the publish step for the merge and Medida export. This is slightly more plumbing, but as a result we get much more straightforward code.

Checklist

  • Reviewed the contributing document
  • Rebased on top of master (no merge commits)
  • Ran clang-format v8.0.0 (via make format or the Visual Studio extension)
  • Compiles
  • Ran all tests
  • If change impacts performance, include supporting evidence per the performance document

Copilot AI balanced review requested due to automatic review settings August 28, 2026 21:07
@dmkozh
dmkozh force-pushed the apply_metrics_no_sync branch from 716025f to 0ce3397 Compare August 28, 2026 21:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors Soroban metrics collection to use thread-local accumulators and publish merged results after ledger close.

Changes:

  • Introduces SorobanApplyMetrics and SorobanMetricsRegistry.
  • Plumbs accumulators through transaction and operation apply paths.
  • Merges worker metrics before Medida publication.

Reviewed changes

Copilot reviewed 27 out of 27 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/transactions/TransactionFrameBase.h Extends apply interfaces with metrics.
src/transactions/TransactionFrame.h Updates transaction method declarations.
src/transactions/TransactionFrame.cpp Records metrics in supplied accumulators.
src/transactions/test/TransactionTestFrame.h Updates test wrapper interfaces.
src/transactions/test/TransactionTestFrame.cpp Supplies test-local accumulators.
src/transactions/RestoreFootprintOpFrame.h Updates restore-operation interfaces.
src/transactions/RestoreFootprintOpFrame.cpp Redirects restore metrics.
src/transactions/ParallelApplyUtils.h Extends parallel-state interfaces.
src/transactions/ParallelApplyUtils.cpp Passes metrics during pre-apply.
src/transactions/OperationFrame.h Extends operation apply interfaces.
src/transactions/OperationFrame.cpp Forwards operation metrics.
src/transactions/InvokeHostFunctionOpFrame.h Updates host-function interfaces.
src/transactions/InvokeHostFunctionOpFrame.cpp Accumulates host-function metrics locally.
src/transactions/FeeBumpTransactionFrame.h Updates fee-bump interfaces.
src/transactions/FeeBumpTransactionFrame.cpp Forwards metrics to inner transactions.
src/transactions/ExtendFootprintTTLOpFrame.h Updates TTL-extension interfaces.
src/transactions/ExtendFootprintTTLOpFrame.cpp Redirects TTL metrics.
src/test/fuzz/targets/TxFuzzTarget.cpp Supplies fuzz-local metrics.
src/main/AppConnector.h Exposes renamed metrics registry.
src/main/AppConnector.cpp Returns renamed registry type.
src/ledger/SorobanMetrics.h Defines accumulators and registry.
src/ledger/SorobanMetrics.cpp Implements merging and publication.
src/ledger/LedgerManagerImpl.h Extends ledger-apply metrics plumbing.
src/ledger/LedgerManagerImpl.cpp Collects, merges, and publishes metrics.
src/ledger/LedgerManager.h Updates ledger manager interfaces.
src/ledger/InMemorySorobanState.h Uses renamed registry type.
src/ledger/InMemorySorobanState.cpp Updates registry parameters.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/transactions/TransactionFrame.cpp
Comment thread src/transactions/TransactionFrame.cpp
Comment thread src/ledger/LedgerManagerImpl.cpp
Comment thread src/ledger/SorobanMetrics.h
Copilot AI review requested due to automatic review settings August 28, 2026 21:12
@dmkozh
dmkozh force-pushed the apply_metrics_no_sync branch from 0ce3397 to 68520aa Compare August 28, 2026 21:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 1 comment.

Suppressed comments (2)

src/transactions/TransactionFrame.cpp:2167

  • This timer no longer honors DISABLE_SOROBAN_METRICS_FOR_TESTING: the clock reads and vector append still run and the samples are published, even though this switch exists specifically to remove metric overhead from apply-load benchmarks. The previous BatchedTimerScope was also RAII, whereas the append at line 2198 is skipped when the exception handler below converts an apply exception into txINTERNAL_ERROR. Please make the local timer conditional and scope-based so disabled runs do no timing/allocation and exceptional applies retain their timer sample.
        auto applyStart = std::chrono::steady_clock::now();

src/ledger/LedgerManagerImpl.cpp:2632

  • This transaction timer now runs unconditionally, so DISABLE_SOROBAN_METRICS_FOR_TESTING still pays for two clock reads, vector growth, and later Medida publication per parallel transaction. That regresses the benchmark switch’s documented purpose and differs from the sequential apply timer, which still checks the flag. Guard both timing and sample insertion with config.DISABLE_SOROBAN_METRICS_FOR_TESTING.
        auto applyStart = std::chrono::steady_clock::now();

Comment on lines +2678 to +2682
// Stages may contain a different number of clusters, so we ensure that
// there is a corresponding metrics entry for each cluster.
if (sorobanApplyMetricsPerThread.size() < stage.numClusters())
{
sorobanApplyMetricsPerThread.resize(stage.numClusters());
The previous attempt at batching Soroban metrics still had some locks and was overall more convoluted than it needs to be. With this change we simply give every thread its own metrics batch to write to, and then cleanly move the batches to the publish step for the merge and Medida export. This is slightly more plumbing, but as a result we get much more straightforward code.
Copilot AI review requested due to automatic review settings August 28, 2026 22:30
@dmkozh
dmkozh force-pushed the apply_metrics_no_sync branch from 68520aa to 144c332 Compare August 28, 2026 22:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated no new comments.

Suppressed comments (1)

src/ledger/LedgerManagerImpl.cpp:2682

  • This is a performance-focused change to the parallel apply hot path, but the PR provides no benchmark evidence that it improves throughput/latency without regression. CONTRIBUTING.md:56-60 requires such evidence for performance-impacting changes; please include representative before/after results, especially since the new per-cluster vector storage and merge may trade lock contention for allocation/cache costs.
    // Stages may contain a different number of clusters, so we ensure that
    // there is a corresponding metrics entry for each cluster.
    if (sorobanApplyMetricsPerThread.size() < stage.numClusters())
    {
        sorobanApplyMetricsPerThread.resize(stage.numClusters());

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.

2 participants