Skip to content
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

ci(l2): automate flamegraph tests #1366

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
52da6ca
script that watches balance of account
dsocolobsky Nov 29, 2024
441fc6a
Run flamegraph reporting in Github CI
dsocolobsky Dec 2, 2024
1ce321d
feat(cli/ethrex_l2): allow --default parameter in "ethrex_l2 config c…
dsocolobsky Dec 2, 2024
f9cb7bc
fix: create ethrex_l2 config in flamegraph_reporter.yaml
dsocolobsky Dec 2, 2024
d3679ec
Make load test retry if connection failed
dsocolobsky Dec 2, 2024
37fcfd1
Use addr2line for faster perf usage
dsocolobsky Dec 3, 2024
122a4a8
Use addr2line for faster perf usage 2
dsocolobsky Dec 3, 2024
830159f
Run perf with --no-inline to make it faster
dsocolobsky Dec 3, 2024
967e79e
Run perf with --no-inline to make it faster (2)
dsocolobsky Dec 3, 2024
fbb456f
Run inferno-collapse-perf with --tid parameter
dsocolobsky Dec 3, 2024
803a72f
Run inferno-collapse-perf without --tid parameter
dsocolobsky Dec 3, 2024
0b783ea
Run flamegraph for reth as well
dsocolobsky Dec 4, 2024
6349a7a
Run flamegraph for reth in parallel in a separate job
dsocolobsky Dec 4, 2024
89799a3
Add balance to account in genesis-load-test.json
dsocolobsky Dec 4, 2024
5d3429c
Run cargo flamegraph with perf options
dsocolobsky Dec 4, 2024
0dd0e05
Adjust paths in workflow
dsocolobsky Dec 4, 2024
71b2c5d
Adjust paths in workflow 2
dsocolobsky Dec 4, 2024
73c5edf
Deploy page workflow
dsocolobsky Dec 4, 2024
b128f48
Update deployed page with generated flamegraphs
dsocolobsky Dec 5, 2024
9a7c430
Update deployed page with generated flamegraphs 2
dsocolobsky Dec 5, 2024
29d50a4
Fix .svg paths
dsocolobsky Dec 5, 2024
2d2160b
Add elapsed time for each test to static page
dsocolobsky Dec 5, 2024
320acec
Use Github Action Outputs for test times
dsocolobsky Dec 5, 2024
bc4b4f1
Merge branch 'main' into automate-perf-tests
dsocolobsky Dec 5, 2024
11c6696
Merge branch 'main' into automate-perf-tests
dsocolobsky Dec 6, 2024
5f6d547
Run a 1000 iterations for the load tests.
dsocolobsky Dec 6, 2024
201ab7a
Minor adjustments and cleanup for flamegraph_reporter.yaml
dsocolobsky Dec 6, 2024
6b0c5e2
Simplify flamegraph script into a single one.
dsocolobsky Dec 6, 2024
5db6105
Metadata for Slack link previews
dsocolobsky Dec 6, 2024
43689a8
Send daily flamegraph report via Slack
dsocolobsky Dec 6, 2024
3ff3063
Measure load test time more accurately
dsocolobsky Dec 6, 2024
19e8b78
Fix local script
dsocolobsky Dec 6, 2024
91e0b87
Send direct links to .svg files in Slack
dsocolobsky Dec 6, 2024
dbec9c7
Fix local script "make flamegraph"
dsocolobsky Dec 6, 2024
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
28 changes: 28 additions & 0 deletions .github/scripts/flamegraph.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

iterations=10
value=10000000
account=0x33c6b73432B3aeA0C1725E415CC40D04908B85fd
end_val=$((172 * $iterations * $value))

ethrex_l2 test load --path /home/runner/work/ethrex/ethrex/test_data/private_keys.txt -i $iterations -v --value $value --to $account

start_time=$(date +%s)
output=$(cast balance $account --rpc-url=http://localhost:1729 2>&1)
retries=0
while [[ $output -le $end_val && $retries -lt 30 ]]; do
sleep 5
output=$(cast balance $account --rpc-url=http://localhost:1729 2>&1)
echo "balance was $output still not reached value of $end_val (retry $retries/30)"
((retries++))
done
end_time=$(date +%s)
elapsed_time=$((end_time - start_time))
minutes=$((elapsed_time / 60))
seconds=$((elapsed_time % 60))
echo "Balance of $output reached in $minutes min $seconds s, killing process ethrex"

sudo pkill ethrex && while pgrep -l "cargo-flamegraph"; do echo "waiting for reth to exit... "; sleep 1;done;

# We need this for the following job, to add to the static page
echo "time=$minutes minutes $seconds seconds" >> "$GITHUB_OUTPUT"
28 changes: 28 additions & 0 deletions .github/scripts/flamegraph_reth.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

iterations=10
value=10000000
account=0x33c6b73432B3aeA0C1725E415CC40D04908B85fd
end_val=$((172 * $iterations * $value))

ethrex_l2 test load --path /home/runner/work/ethrex/ethrex/test_data/private_keys.txt -i $iterations -v --value $value --to $account

start_time=$(date +%s)
output=$(cast balance $account --rpc-url=http://localhost:1729 2>&1)
retries=0
while [[ $output -le $end_val && $retries -lt 30 ]]; do
sleep 5
output=$(cast balance $account --rpc-url=http://localhost:1729 2>&1)
echo "balance was $output still not reached value of $end_val (retry $retries/30)"
((retries++))
done
end_time=$(date +%s)
elapsed_time=$((end_time - start_time))
minutes=$((elapsed_time / 60))
seconds=$((elapsed_time % 60))
echo "Balance of $output reached in $minutes min $seconds s, killing process reth"

sudo pkill reth && while pgrep -l "cargo-flamegraph"; do echo "waiting for reth to exit... "; sleep 1;done;

# We need this for the following job, to add to the static page
echo "time=$minutes minutes $seconds seconds" >> "$GITHUB_OUTPUT"
209 changes: 209 additions & 0 deletions .github/workflows/flamegraph_reporter.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
name: Daily Flamegraph Reporter
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! Not sure if it's daily though, I forgot I had named it like that but I think it's supposed to run in each merge to master; I will ask Javi/Ivan.


permissions:
contents: read
pages: write
id-token: write

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "**" ]
workflow_dispatch:

env:
RUST_VERSION: 1.81.0
RUST_RETH_VERSION: 1.82.0

jobs:
flamegraph-ethrex:
name: Generate Flamegraph for Ethrex
runs-on: ubuntu-latest
outputs:
time: ${{steps.generate-flamegraph-ethrex.outputs.time}}
steps:
- name: Checkout sources
uses: actions/checkout@v4

- name: Rustup toolchain install
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.RUST_VERSION }}

- name: Caching
uses: Swatinem/rust-cache@v2

- name: Change perf settings
run: |
sudo sysctl kernel.perf_event_paranoid=-1
sudo perf list hw

- name: Install flamegraph
run: |
cargo install flamegraph
cargo install inferno

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Install ethrex_l2 cli
run: |
cargo install --path cmd/ethrex_l2
ethrex_l2 config create default --default
ethrex_l2 config set default

- name: Build ethrex
run: CARGO_PROFILE_RELEASE_DEBUG=true cargo build --release --bin ethrex --features dev

- id: generate-flamegraph-ethrex
name: Generate Flamegraph data for Ethrex
shell: bash
run: |
CARGO_PROFILE_RELEASE_DEBUG=true cargo flamegraph -c "record -o perf.data -F997 --call-graph dwarf,16384 -g" \
--bin ethrex --features dev -- --network /home/runner/work/ethrex/ethrex/test_data/genesis-l2.json --http.port 1729 &
echo "waiting to execute load test..."
sleep 30 &&
echo "executing load test..."
bash .github/scripts/flamegraph.sh &&
echo "Load test finished"

- name: Generate SVG
shell: bash
run: |
echo "running perf"
perf script -v -i perf.data --no-inline > stack.data
inferno-collapse-perf < stack.data > collapsed.data
inferno-flamegraph < collapsed.data > flamegraph_ethrex.svg
file flamegraph_ethrex.svg

- name: Upload artifacts - flamegraph_ethrex.svg
uses: actions/upload-artifact@v4
with:
name: flamegraph_ethrex.svg
path: ./flamegraph_ethrex.svg

flamegraph-reth:
name: Generate Flamegraph for Reth
runs-on: ubuntu-latest
outputs:
time: ${{steps.generate-flamegraph-reth.outputs.time}}
steps:
- name: Checkout sources
uses: actions/checkout@v4

- name: Rustup toolchain install
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.RUST_RETH_VERSION }}

- name: Caching
uses: Swatinem/rust-cache@v2

- name: Change perf settings
run: |
pwd
sudo sysctl kernel.perf_event_paranoid=-1
sudo perf list hw

- name: Install flamegraph
run: |
cargo install flamegraph
cargo install inferno

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Install ethrex_l2 cli
run: |
cargo install --path cmd/ethrex_l2
ethrex_l2 config create default --default
ethrex_l2 config set default

- name: Checkout reth
uses: actions/checkout@v4
with:
repository: paradigmxyz/reth
path: 'reth'

- id: generate-flamegraph-reth
name: Build and test reth
shell: bash
run: |
cd ./reth
cargo flamegraph -c "record -o perf.data -F997 --call-graph dwarf,16384 -g" --bin reth --profile profiling \
-- node --chain /home/runner/work/ethrex/ethrex/test_data/genesis-load-test.json --dev \
--dev.block-time 5000ms --http.port 1729 --txpool.max-pending-txns 100000000 --txpool.max-new-txns 1000000000 \
--txpool.pending-max-count 100000000 --txpool.pending-max-size 10000000000 --txpool.basefee-max-count 100000000000 \
--txpool.basefee-max-size 1000000000000 --txpool.queued-max-count 1000000000 &
echo "waiting to execute load test..."
sleep 120 &&
bash /home/runner/work/ethrex/ethrex/.github/scripts/flamegraph_reth.sh &&
echo "Load test finished"
ls -las

- name: Generate SVG
shell: bash
run: |
pwd
echo "running perf 2"
ls -las /home/runner/work/ethrex/
ls -las /home/runner/work/ethrex/ethrex/
perf script -v -i /home/runner/work/ethrex/ethrex/reth/perf.data --no-inline > stack.data
inferno-collapse-perf < stack.data > collapsed.data
inferno-flamegraph < collapsed.data > flamegraph_reth.svg
file flamegraph_reth.svg

- name: Upload artifacts - flamegraph_reth.svg
uses: actions/upload-artifact@v4
with:
name: flamegraph_reth.svg
path: ./flamegraph_reth.svg

upload-static-page:
name: Upload artifacts for static page
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
needs: [ flamegraph-ethrex, flamegraph-reth ]
steps:
- name: Checkout sources
uses: actions/checkout@v4

- name: Download ethrex flamegraph artifact
uses: actions/download-artifact@v4
with:
name: flamegraph_ethrex.svg
path: flamegraph_ethrex.svg

- name: Download reth flamegraph artifact
uses: actions/download-artifact@v4
with:
name: flamegraph_reth.svg
path: flamegraph_reth.svg

- name: Update static page locally with new data
shell: bash
run: |
file flamegraph_ethrex.svg
file flamegraph_reth.svg
cp -r flamegraph_ethrex.svg pages/
cp -r flamegraph_reth.svg pages/
ls -las pages/
date +'%Y-%m-%dT%H:%M:%S'
sed -i "s/{{LAST_UPDATE}}/$(date +'%Y-%m-%dT%H:%M:%S')/g" pages/index.html
sed -i "s/{{ETHREX_TIME}}/${{ needs.flamegraph-ethrex.outputs.time }}/g" pages/index.html
sed -i "s/{{RETH_TIME}}/${{ needs.flamegraph-reth.outputs.time }}/g" pages/index.html

- name: Setup Pages
uses: actions/configure-pages@v5

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: 'pages/'

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,9 @@ clean-hive-logs: ## 🧹 Clean Hive logs

loc:
cargo run -p loc

flamegraph:
sudo -E CARGO_PROFILE_RELEASE_DEBUG=true cargo flamegraph --bin ethrex --features dev -- --network test_data/genesis-l2.json --http.port 1729

test-load:
ethrex_l2 test load --path ./test_data/private_keys.txt -i 1000 -v --value 10000000 --to 0xFCbaC0713ACf16708aB6BC977227041FA1BC618D
24 changes: 18 additions & 6 deletions cmd/ethrex_l2/src/commands/config.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::utils::config::default_config;
use crate::utils::{
config::{
config_file_names, config_path, config_path_interactive_selection, confirm,
Expand Down Expand Up @@ -28,7 +29,11 @@ pub(crate) enum Command {
opts: Box<EditConfigOpts>,
},
#[clap(about = "Create a new config.")]
Create { config_name: String },
Create {
config_name: String,
#[arg(long = "default", required = false)]
default: bool,
},
#[clap(about = "Set the config to use.")]
Set {
#[arg(
Expand Down Expand Up @@ -99,7 +104,7 @@ impl Command {
let (new_config, config_path) = if let Some(ref config_name) = config_name {
let config_path = config_path(config_name)?;
if !config_path.exists() {
return confirm_config_creation(config_name.clone()).await;
return confirm_config_creation(config_name.clone(), false).await;
}
let new_config = if opts.is_empty() {
edit_config_by_name_interactively(&config_path)?
Expand All @@ -117,7 +122,10 @@ impl Command {
}
set_new_config(config_path.clone(), show).await?;
}
Command::Create { config_name } => {
Command::Create {
config_name,
default,
} => {
let config_path = config_path(&config_name)?;
if config_path.exists() {
let override_confirmation = confirm(CONFIG_OVERRIDE_PROMPT_MSG)?;
Expand All @@ -126,7 +134,11 @@ impl Command {
return Ok::<(), eyre::Error>(());
}
}
let config = prompt_config()?;
let config = if default {
default_config()?
} else {
prompt_config()?
};
let toml_config = toml::to_string_pretty(&config)?;
println!(
"Config created at: {}\n{toml_config}",
Expand All @@ -138,7 +150,7 @@ impl Command {
let config_path_to_select = if let Some(config_name) = config_name {
let config_path_to_select = config_path(&config_name)?;
if !config_path_to_select.exists() {
return confirm_config_creation(config_name).await;
return confirm_config_creation(config_name, false).await;
}
config_path_to_select
} else {
Expand All @@ -154,7 +166,7 @@ impl Command {
let config_to_display_path = if let Some(config_name) = config_name {
let config_to_display_path = config_path(&config_name)?;
if !config_to_display_path.exists() {
return confirm_config_creation(config_name).await;
return confirm_config_creation(config_name, false).await;
}
config_to_display_path
} else {
Expand Down
Loading
Loading