Skip to content

Add test to re-execute specified range of mainnet C-Chain blocks #4019

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 108 commits into
base: master
Choose a base branch
from

Conversation

aaronbuchwald
Copy link
Collaborator

@aaronbuchwald aaronbuchwald commented Jun 17, 2025

Why this should be merged

This PR adds a configurable C-Chain benchmark that can be run locally with Taskfile or via GitHub Action (this PR currently includes triggers for pull requests and manual GH Action, but this should be changed to a cronjob on master and manual GH Action before merge and once done testing).

The test clones a block database and current state database, so that it can execute a range of blocks starting from the state at an arbitrary height N.

The CI workflow copies the data from an S3 Bucket in the Ava Labs Experimental Account in us-east-2 and requires AWS credentials to be provided. It can also be used with local file system directory paths for use on Snoopy/Linus (dedicated machines with large SSDs used for Firewood testing).

How this works

Constructs an EVM instance mimicking the params passed in from AvalancheGo including passing in a metrics registry with the expected prefix and chain labels attached to it, so that it can be used directly with existing Grafana Dashboards used with tmpnet rather than needing to maintain an alternative without the prefixes/labels.

How this was tested

This has been tested by running in CI and running through the steps documented in the README. To review this PR, please walk through the steps in the benchmark README.

Need to be documented in RELEASES.md?

No.

Recommended Changes Before Merge

  • Remove PR trigger in favor of weekly cronjob (currently in use to trigger while testing this PR)

Recommended Fast Follow Ups to this PR

  • Identify the best place to run this job ie. ARC, self-hosted runner, Blacksmith, etc.
  • Integrate GitHub Action Benchmark performance tracking on master by setting up gh-pages branch or a separate repo (demo of what this will look like on my fork of Canoto here

Potential Future Work

  • Identify a reasonable micro-benchmark that can be run on every PR and provide a reasonable signal whether the change triggers a performance improvement or degradation
  • Implement a job to re-execute the entire C-Chain history for full coverage that uses multiple snapshots and executes multiple subranges in parallel (ie. [0, 5m], [5m, 10m], etc.)
  • Implement a task/job to archive all blocks over configured ranges to S3 by fetching directly from the network
  • Add an optional feature at the end of the re-execution job that can post the resulting state to S3 (useful for manual GH Action entry point to create new current state snapshots)
  • Add support for long-lived feature branches or alternative configurations to run as a cronjob in addition to the default configuration run on the master branch of AvalancheGo
  • Support multiple configurations (archive/full) and targets (EBS, SSD, etc) to run the benchmark against
  • Support all VMs (P-Chain and X-Chain) for complete test coverage and benchmarking other VMs performance
  • Provide a "How-To Guide" for custom VM testing using the same approach

@aaronbuchwald aaronbuchwald changed the title Aaronbuchwald/cchain reexecute range test test(cchain): Add test to re-execute specified range of mainnet blocks Jun 17, 2025
@aaronbuchwald aaronbuchwald changed the title test(cchain): Add test to re-execute specified range of mainnet blocks Add test to re-execute specified range of mainnet C-Chain blocks Jun 17, 2025
Comment on lines 63 to 73
- name: Download Previous Benchmark Result
uses: actions/cache@v4
with:
path: ./cache
key: ${{ runner.os }}-reexecute-cchain-range-benchmark.json
- name: Compare Benchmark Results
uses: benchmark-action/github-action-benchmark@v1
with:
tool: 'go'
output-file-path: $GITHUB_WORKSPACE/reexecution-data/reexecute-cchain-range.txt
external-data-json-path: ./cache/${{ runner.os }}-reexecute-cchain-range-benchmark.json
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Writing to the cache and comparing against the last entry enables a comparison.

This should be changed to write to the cache only on the master branch for comparison and other triggers should compare against the latest baseline set by master

@aaronbuchwald aaronbuchwald marked this pull request as ready for review July 16, 2025 18:53
@aaronbuchwald aaronbuchwald requested a review from maru-ava as a code owner July 16, 2025 18:53
@aaronbuchwald
Copy link
Collaborator Author

Trying out running on ARC and Blacksmith here:

Copy link
Contributor

@StephenButtolph StephenButtolph left a comment

Choose a reason for hiding this comment

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

I agree with most of Maru's comments, my only real additional question is:

Comment on lines 84 to 86
func BenchmarkReexecuteRange(b *testing.B) {
benchmarkReexecuteRange(b, sourceBlockDirArg, targetDirArg, startBlockArg, endBlockArg, chanSizeArg, metricsEnabledArg)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this correct usage of golang Benchmark tests? I've never seen a benchmark that didn't utilize b.N to repeatedly run the benchmark.

Copy link
Collaborator Author

@aaronbuchwald aaronbuchwald Jul 17, 2025

Choose a reason for hiding this comment

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

This is definitely a bastardization to produce the benchmark output and requires setting -benchtime=1x. Will document this and make sure it fails loudly. The expectation here is that it is going to overwrite the current-state and does not handle reverting or creating a new copy of the same thing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Adding:

require.Equalf(b, 1, b.N, "BenchmarkReexecuteRange expects to run a single iteration because it overwrites the input current-state, but found (b.N=%d)", b.N)

Copy link
Contributor

@maru-ava maru-ava left a comment

Choose a reason for hiding this comment

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

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

3 participants