Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.DS_Store
/.idea/
/bin/
**/bin/
data-dir/
output/
.vercel
Expand All @@ -10,3 +10,12 @@ contracts/cache/
contracts/out/
contracts/abi/
benchmark/benchmark

.env

# Node
coverage/
!**/__fixtures__/coverage
node_modules
yarn-debug.log*
yarn-error.log*
23 changes: 23 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ LDFLAGSSTRING +=-X main.GitDate=$(GITDATE)
LDFLAGSSTRING +=-X main.Version=$(VERSION)
LDFLAGS := -ldflags "$(LDFLAGSSTRING)"

# Include .env file if it exists
-include .env

# first so that make defaults to building the benchmark
.PHONY: build
build:
Expand Down Expand Up @@ -50,3 +53,23 @@ build-rbuilder:

.PHONY: build-binaries
build-binaries: build-reth build-geth build-rbuilder

.PHONY: build-backend
build-backend:
cd report/backend && env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) CGO_ENABLED=0 go build -v $(LDFLAGS) -o ../../bin/base-bench-api cmd/main.go

.PHONY: build-frontend
build-frontend:
cd report && yarn build

.PHONY: run-backend
run-backend:
./bin/base-bench-api --s3-bucket ${BASE_BENCH_API_S3_BUCKET}

.PHONY: run-frontend
run-frontend:
cd report && yarn dev

.PHONY: run-backfill
run-backfill:
./bin/base-bench backfill-benchmark-run-id --s3-bucket ${BASE_BENCH_API_S3_BUCKET} metadata.json
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ git submodule update --init --recursive
# Build the application
make build

# Build the binaries, geth, reth, rbuilder
make build-binaries

# Run the basic benchmark
./bin/base-bench run \
--config ./configs/public/basic.yml \
Expand All @@ -39,6 +42,18 @@ make build
--geth-bin path_to_geth_bin \
--output-dir ./output

# Run the basic benchmark with S3
./bin/base-bench run \
--config ./configs/public/basic.yml \
--root-dir ./data-dir \
--reth-bin path_to_reth_bin \
--geth-bin path_to_geth_bin \
--output-dir ./output \
--enable-s3=true --s3-bucket <bucket-name>

# Upload the results to S3
./bin/base-bench export-to-cloud --output-dir ./output --s3-bucket <bucket-name>

# View the interactive dashboard
cd report/
npm i
Expand Down Expand Up @@ -132,6 +147,10 @@ OPTIONS:
--geth-auth-rpc-port value Auth RPC port (default: 8551)
--geth-metrics-port value Metrics port (default: 8080)

# S3 Configuration
--enable-s3 value Enable S3 (default: false)
--s3-bucket value S3 bucket name (default: "base-benchmarking-results-dev")

# General Options
--proxy-port value Proxy port (default: 8546)
--help, -h Show help (default: false)
Expand Down
97 changes: 97 additions & 0 deletions SNAPSHOT_SYSTEM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Two-Tier Snapshot System

## Overview

The benchmarking framework now supports an optimized two-tier snapshot system that significantly improves performance and reduces network overhead when running multiple tests with snapshots.

## Architecture

### Tier 1: Initial Snapshots
- **Purpose**: Downloaded once at benchmark startup and stored persistently
- **Location**: Typically `/data/snapshots/initial_<nodeType>_<hash>`
- **Lifecycle**: Created at benchmark startup, persisted across all tests
- **Usage**: Serves as the source for per-test copies

### Tier 2: Per-Test Snapshots
- **Purpose**: Test-specific copies created from initial snapshots
- **Location**: Test-specific temporary directories
- **Lifecycle**: Created before each test, cleaned up after test completion
- **Usage**: Isolated environment for each test run

## Configuration Format

### New YAML Structure

```yaml
benchmarks:
- initial_snapshots:
- node_type: reth
command: ./scripts/setup-initial-snapshot.sh --network=sepolia --node-type=reth
superchain_chain_id: 84532
- node_type: geth
command: ./scripts/setup-initial-snapshot.sh --network=sepolia --node-type=geth
superchain_chain_id: 84532
variables:
- type: node_type
values: [reth, geth]
# ... other variables
```

## Implementation Details

### Key Components

1. **SnapshotManager Interface** (`benchmark/snapshots.go`)
- `EnsureInitialSnapshot()`: Creates initial snapshots
- `GetInitialSnapshotPath()`: Retrieves initial snapshot paths
- `CopyFromInitialSnapshot()`: Copies using rsync for efficiency

2. **TestDefinition** (`benchmark/definition.go`)
- `InitialSnapshots []SnapshotDefinition`: Tier 1 snapshots

3. **Service** (`runner/service.go`)
- `setupInitialSnapshots()`: Runs at benchmark startup
- `setupInternalDirectories()`: Uses rsync for per-test copies

### Execution Flow

1. **Benchmark Startup**
```
Service.Run() → setupInitialSnapshots() → EnsureInitialSnapshot()
```

2. **Per Test Execution**
```
runTest() → setupInternalDirectories() → CopyFromInitialSnapshot()
```

3. **Test Cleanup**
```
defer cleanup → os.RemoveAll(testDir) // Removes per-test copies only
```

## Usage Examples

### Multi-Node Type Testing
```yaml
initial_snapshots:
- node_type: reth
command: ./download-reth-snapshot.sh
- node_type: geth
command: ./download-geth-snapshot.sh
variables:
- type: node_type
values: [reth, geth]
```

### Fallback Support
If no initial snapshot exists for a node type, the system automatically falls back to the original single-tier behavior, ensuring backward compatibility.

### Mixed Scenarios
```yaml
# Test plan 1: Uses two-tier system
- initial_snapshots: [...]

# Test plan 2: Uses single-tier system
- initial_snapshots: [...] # No initial_snapshots
```
38 changes: 38 additions & 0 deletions benchmark/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/base/base-bench/benchmark/config"
"github.com/base/base-bench/benchmark/flags"
"github.com/base/base-bench/runner"
"github.com/base/base-bench/runner/aws"
"github.com/base/base-bench/runner/importer"
"github.com/urfave/cli/v2"

Expand Down Expand Up @@ -46,6 +47,13 @@ func main() {
Description: "Import benchmark runs from local metadata.json or remote URL into existing output metadata.json. Use --src-tag and --dest-tag to apply tags to runs, or use interactive mode.",
ArgsUsage: "[metadata-file-or-url]",
},
{
Name: "export-to-cloud",
Flags: cliapp.ProtectFlags(flags.ExportFlags),
Action: ExportMain(Version),
Usage: "export output directory to S3",
Description: "Export the entire output directory to AWS S3 bucket and sync with remote metadata.json.",
},
}
app.Flags = flags.Flags
app.Version = opservice.FormatVersion(Version, GitCommit, GitDate, "")
Expand Down Expand Up @@ -185,3 +193,33 @@ func ImportMain(version string) cli.ActionFunc {
return nil
}
}

func ExportMain(version string) cli.ActionFunc {
return func(cliCtx *cli.Context) error {
cfg := config.NewExportCmdConfig(cliCtx)
if err := cfg.Check(); err != nil {
return fmt.Errorf("invalid CLI flags: %w", err)
}

l := oplog.NewLogger(oplog.AppOut(cliCtx), oplog.DefaultCLIConfig())
oplog.SetGlobalLogHandler(l.Handler())

// Initialize S3 service
s3Service, err := aws.NewS3Service(cfg.S3Bucket(), l)
if err != nil {
return fmt.Errorf("failed to initialize S3 service: %w", err)
}

// Export output directory to S3
err = s3Service.ExportOutputDirectory(cfg.OutputDir())
if err != nil {
return fmt.Errorf("failed to export output directory to S3: %w", err)
}

fmt.Printf("✅ Export completed successfully!\n")
fmt.Printf(" • Output directory: %s\n", cfg.OutputDir())
fmt.Printf(" • S3 bucket: %s\n", cfg.S3Bucket())

return nil
}
}
45 changes: 45 additions & 0 deletions benchmark/config/export_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package config

import (
"fmt"

"github.com/base/base-bench/benchmark/flags"
"github.com/urfave/cli/v2"
)

// ExportCmdConfig represents the configuration for the export-to-cloud command
type ExportCmdConfig struct {
outputDir string
s3Bucket string
}

// NewExportCmdConfig creates a new export command config from CLI context
func NewExportCmdConfig(cliCtx *cli.Context) *ExportCmdConfig {
return &ExportCmdConfig{
outputDir: cliCtx.String(flags.OutputDirFlagName),
s3Bucket: cliCtx.String(flags.S3BucketFlagName),
}
}

// OutputDir returns the output directory path
func (c *ExportCmdConfig) OutputDir() string {
return c.outputDir
}

// S3Bucket returns the S3 bucket name
func (c *ExportCmdConfig) S3Bucket() string {
return c.s3Bucket
}

// Check validates the export command configuration
func (c *ExportCmdConfig) Check() error {
if c.outputDir == "" {
return fmt.Errorf("output directory is required")
}

if c.s3Bucket == "" {
return fmt.Errorf("S3 bucket is required for export command")
}

return nil
}
8 changes: 8 additions & 0 deletions benchmark/flags/export_flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package flags

import "github.com/urfave/cli/v2"

var ExportFlags = []cli.Flag{
OutputDirFlag,
S3BucketFlag,
}
68 changes: 63 additions & 5 deletions benchmark/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,18 @@ func prefixEnvVars(name string) []string {
}

const (
ConfigFlagName = "config"
RootDirFlagName = "root-dir"
OutputDirFlagName = "output-dir"
TxFuzzBinFlagName = "tx-fuzz-bin"
ProxyPortFlagName = "proxy-port"
ConfigFlagName = "config"
RootDirFlagName = "root-dir"
OutputDirFlagName = "output-dir"
EnableS3FlagName = "enable-s3"
S3BucketFlagName = "s3-bucket"
TxFuzzBinFlagName = "tx-fuzz-bin"
ProxyPortFlagName = "proxy-port"
BenchmarkRunIDFlagName = "benchmark-run-id"
MachineTypeFlagName = "machine-type"
MachineProviderFlagName = "machine-provider"
MachineRegionFlagName = "machine-region"
FileSystemFlagName = "file-system"
)

// TxFuzz defaults
Expand Down Expand Up @@ -62,6 +69,50 @@ var (
Value: 8546,
EnvVars: prefixEnvVars("PROXY_PORT"),
}

EnableS3Flag = &cli.BoolFlag{
Name: EnableS3FlagName,
Usage: "Enable S3 upload of benchmark results",
EnvVars: prefixEnvVars("ENABLE_S3"),
Value: false,
}

S3BucketFlag = &cli.StringFlag{
Name: S3BucketFlagName,
Usage: "S3 bucket name for storing benchmark results",
EnvVars: prefixEnvVars("S3_BUCKET"),
}

BenchmarkRunIDFlag = &cli.StringFlag{
Name: BenchmarkRunIDFlagName,
Usage: "Custom benchmark run ID (auto-generated if not provided)",
EnvVars: prefixEnvVars("BENCHMARK_RUN_ID"),
}

MachineTypeFlag = &cli.StringFlag{
Name: "machine-type",
Usage: "Machine type (e.g., i4i.32xlarge)",
EnvVars: prefixEnvVars("MACHINE_TYPE"),
}

MachineProviderFlag = &cli.StringFlag{
Name: "machine-provider",
Usage: "Cloud provider (aws or gcp)",
EnvVars: prefixEnvVars("MACHINE_PROVIDER"),
}

MachineRegionFlag = &cli.StringFlag{
Name: "machine-region",
Usage: "Machine region",
EnvVars: prefixEnvVars("MACHINE_REGION"),
}

FileSystemFlag = &cli.StringFlag{
Name: "file-system",
Usage: "File system type",
Value: "ext4",
EnvVars: prefixEnvVars("FILE_SYSTEM"),
}
)

// Flags contains the list of configuration options available to the binary.
Expand All @@ -73,6 +124,13 @@ var RunFlags = []cli.Flag{
OutputDirFlag,
TxFuzzBinFlag,
ProxyPortFlag,
EnableS3Flag,
S3BucketFlag,
BenchmarkRunIDFlag,
MachineTypeFlag,
MachineProviderFlag,
MachineRegionFlag,
FileSystemFlag,
}

func init() {
Expand Down
Loading
Loading