Skip to content

Commit b3c907a

Browse files
authored
ci: add cycle count diff (#459)
* ci: add cycle count diff * ci: add author * ci: fix git config * ci: push changes * ci: avoid merge commit * ci: fix not to be in detatched head * ci: fix not to checkout merge ref
1 parent 0a03b73 commit b3c907a

File tree

3 files changed

+312
-0
lines changed

3 files changed

+312
-0
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Cycle Count Diff
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- 'elf/range-elf-embedded'
7+
8+
jobs:
9+
cycle-count-diff:
10+
runs-on:
11+
- runs-on
12+
- cpu=32
13+
- ram=128
14+
- family=m7a+m7i-flex
15+
- image=ubuntu22-full-x64
16+
- run-id=${{ github.run_id }}
17+
steps:
18+
- name: Checkout PR Branch
19+
uses: actions/checkout@v4
20+
with:
21+
ref: ${{ github.head_ref }}
22+
fetch-depth: 0
23+
24+
- name: Setup CI
25+
uses: ./.github/actions/setup
26+
27+
- name: Configure Git
28+
run: |
29+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
30+
git config --global user.name "github-actions[bot]"
31+
32+
- name: Run Test
33+
run: |
34+
RUST_LOG=info cargo test test_cycle_count_diff -- --exact --nocapture
35+
env:
36+
L2_NODE_RPC: ${{ secrets.L2_NODE_RPC }}
37+
L1_RPC: ${{ secrets.L1_RPC }}
38+
L1_BEACON_RPC: ${{ secrets.L1_BEACON_RPC }}
39+
L2_RPC: ${{ secrets.L2_RPC }}
40+
REPO_OWNER: ${{ github.repository_owner }}
41+
REPO_NAME: ${{ github.event.repository.name }}
42+
PR_NUMBER: ${{ github.event.pull_request.number }}
43+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
44+
POST_TO_GITHUB: ${{ github.event_name == 'pull_request' }}
45+
46+
- name: Push Changes
47+
run: |
48+
git push origin ${{ github.head_ref }}
49+
env:
50+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

scripts/prove/base_cycle_stats.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"l1_head": 8049948,
3+
"batch_start": 421000,
4+
"batch_end": 421005,
5+
"witness_generation_time_sec": 0,
6+
"total_execution_time_sec": 993,
7+
"total_instruction_count": 2303907771,
8+
"oracle_verify_instruction_count": 282169100,
9+
"derivation_instruction_count": 1889592216,
10+
"block_execution_instruction_count": 6276306,
11+
"blob_verification_instruction_count": 23479564,
12+
"total_sp1_gas": 3110981625,
13+
"nb_blocks": 5,
14+
"nb_transactions": 5,
15+
"eth_gas_used": 227598,
16+
"l1_fees": 0,
17+
"total_tx_fees": 0,
18+
"cycles_per_block": 460781554,
19+
"cycles_per_transaction": 460781554,
20+
"transactions_per_block": 1,
21+
"gas_used_per_block": 45519,
22+
"gas_used_per_transaction": 45519,
23+
"bn_pair_cycles": 0,
24+
"bn_add_cycles": 0,
25+
"bn_mul_cycles": 0,
26+
"kzg_eval_cycles": 0,
27+
"ec_recover_cycles": 0,
28+
"p256_verify_cycles": 0
29+
}
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
use anyhow::Result;
2+
use std::{fmt::Write as _, fs::File, sync::Arc};
3+
4+
use common::post_to_github_pr;
5+
use op_succinct_host_utils::{
6+
fetcher::OPSuccinctDataFetcher,
7+
get_proof_stdin,
8+
hosts::{default::SingleChainOPSuccinctHost, OPSuccinctHost},
9+
stats::{ExecutionStats, MarkdownExecutionStats},
10+
};
11+
use op_succinct_prove::execute_multi;
12+
13+
mod common;
14+
15+
fn create_diff_report(
16+
base: &ExecutionStats,
17+
current: &ExecutionStats,
18+
range: (u64, u64),
19+
) -> String {
20+
let mut report = String::new();
21+
writeln!(report, "## Performance Comparison\n").unwrap();
22+
writeln!(report, "Range {}~{}\n", range.0, range.1).unwrap();
23+
writeln!(
24+
report,
25+
"| {:<30} | {:<25} | {:<25} | {:<10} |",
26+
"Metric", "Base Branch", "Current PR", "Diff (%)"
27+
)
28+
.unwrap();
29+
writeln!(report, "|--------------------------------|---------------------------|---------------------------|------------|").unwrap();
30+
31+
let diff_percentage = |base: u64, current: u64| -> f64 {
32+
if base == 0 {
33+
return 0.0;
34+
}
35+
((current as f64 - base as f64) / base as f64) * 100.0
36+
};
37+
38+
let write_metric = |report: &mut String, name: &str, base_val: u64, current_val: u64| {
39+
let diff = diff_percentage(base_val, current_val);
40+
writeln!(
41+
report,
42+
"| {:<30} | {:<25} | {:<25} | {:>9.2}% |",
43+
name,
44+
base_val.to_string(),
45+
current_val.to_string(),
46+
diff
47+
)
48+
.unwrap();
49+
};
50+
51+
// Add key metrics with their comparisons
52+
write_metric(
53+
&mut report,
54+
"Total Instructions",
55+
base.total_instruction_count,
56+
current.total_instruction_count,
57+
);
58+
write_metric(
59+
&mut report,
60+
"Oracle Verify Cycles",
61+
base.oracle_verify_instruction_count,
62+
current.oracle_verify_instruction_count,
63+
);
64+
write_metric(
65+
&mut report,
66+
"Derivation Cycles",
67+
base.derivation_instruction_count,
68+
current.derivation_instruction_count,
69+
);
70+
write_metric(
71+
&mut report,
72+
"Block Execution Cycles",
73+
base.block_execution_instruction_count,
74+
current.block_execution_instruction_count,
75+
);
76+
write_metric(
77+
&mut report,
78+
"Blob Verification Cycles",
79+
base.blob_verification_instruction_count,
80+
current.blob_verification_instruction_count,
81+
);
82+
write_metric(
83+
&mut report,
84+
"Total SP1 Gas",
85+
base.total_sp1_gas,
86+
current.total_sp1_gas,
87+
);
88+
write_metric(
89+
&mut report,
90+
"Cycles per Block",
91+
base.cycles_per_block,
92+
current.cycles_per_block,
93+
);
94+
write_metric(
95+
&mut report,
96+
"Cycles per Transaction",
97+
base.cycles_per_transaction,
98+
current.cycles_per_transaction,
99+
);
100+
write_metric(
101+
&mut report,
102+
"BN Pair Cycles",
103+
base.bn_pair_cycles,
104+
current.bn_pair_cycles,
105+
);
106+
write_metric(
107+
&mut report,
108+
"BN Add Cycles",
109+
base.bn_add_cycles,
110+
current.bn_add_cycles,
111+
);
112+
write_metric(
113+
&mut report,
114+
"BN Mul Cycles",
115+
base.bn_mul_cycles,
116+
current.bn_mul_cycles,
117+
);
118+
write_metric(
119+
&mut report,
120+
"KZG Eval Cycles",
121+
base.kzg_eval_cycles,
122+
current.kzg_eval_cycles,
123+
);
124+
write_metric(
125+
&mut report,
126+
"EC Recover Cycles",
127+
base.ec_recover_cycles,
128+
current.ec_recover_cycles,
129+
);
130+
write_metric(
131+
&mut report,
132+
"P256 Verify Cycles",
133+
base.p256_verify_cycles,
134+
current.p256_verify_cycles,
135+
);
136+
137+
report
138+
}
139+
140+
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
141+
async fn test_cycle_count_diff() -> Result<()> {
142+
dotenv::dotenv()?;
143+
144+
let data_fetcher = OPSuccinctDataFetcher::new_with_rollup_config().await?;
145+
146+
let host = SingleChainOPSuccinctHost {
147+
fetcher: Arc::new(data_fetcher.clone()),
148+
};
149+
150+
let base_stats =
151+
serde_json::from_reader::<_, ExecutionStats>(File::open("base_cycle_stats.json")?)?;
152+
let l2_start_block = base_stats.batch_start;
153+
let l2_end_block = base_stats.batch_end;
154+
155+
let host_args = host
156+
.fetch(l2_start_block, l2_end_block, None, Some(false))
157+
.await?;
158+
159+
let oracle = host.run(&host_args).await?;
160+
let sp1_stdin = get_proof_stdin(oracle)?;
161+
let (block_data, report, execution_duration) =
162+
execute_multi(&data_fetcher, sp1_stdin, l2_start_block, l2_end_block).await?;
163+
164+
let l1_block_number = data_fetcher
165+
.get_l1_header(host_args.l1_head.into())
166+
.await
167+
.unwrap()
168+
.number;
169+
let new_stats = ExecutionStats::new(
170+
l1_block_number,
171+
&block_data,
172+
&report,
173+
0,
174+
execution_duration.as_secs(),
175+
);
176+
177+
println!(
178+
"Execution Stats:\n{}",
179+
MarkdownExecutionStats::new(new_stats.clone())
180+
);
181+
182+
let report = create_diff_report(&base_stats, &new_stats, (l2_start_block, l2_end_block));
183+
184+
// Update base_cycle_stats.json with new stats.
185+
let mut file = File::create("base_cycle_stats.json")?;
186+
serde_json::to_writer_pretty(&mut file, &new_stats)?;
187+
188+
// Commit the changes to base_cycle_stats.json
189+
let git_add = std::process::Command::new("git")
190+
.arg("add")
191+
.arg("base_cycle_stats.json")
192+
.output()?;
193+
if !git_add.status.success() {
194+
eprintln!(
195+
"Failed to git add base_cycle_stats.json: {}",
196+
String::from_utf8_lossy(&git_add.stderr)
197+
);
198+
}
199+
200+
let git_commit = std::process::Command::new("git")
201+
.arg("commit")
202+
.arg("-m")
203+
.arg(format!(
204+
"chore: update base cycle stats for blocks {}~{}",
205+
l2_start_block, l2_end_block
206+
))
207+
.output()?;
208+
if !git_commit.status.success() {
209+
eprintln!(
210+
"Failed to git commit base_cycle_stats.json: {}",
211+
String::from_utf8_lossy(&git_commit.stderr)
212+
);
213+
}
214+
215+
if std::env::var("POST_TO_GITHUB")
216+
.ok()
217+
.and_then(|v| v.parse::<bool>().ok())
218+
.unwrap_or_default()
219+
{
220+
if let (Ok(owner), Ok(repo), Ok(pr_number), Ok(token)) = (
221+
std::env::var("REPO_OWNER"),
222+
std::env::var("REPO_NAME"),
223+
std::env::var("PR_NUMBER"),
224+
std::env::var("GITHUB_TOKEN"),
225+
) {
226+
post_to_github_pr(&owner, &repo, &pr_number, &token, &report)
227+
.await
228+
.unwrap();
229+
}
230+
}
231+
232+
Ok(())
233+
}

0 commit comments

Comments
 (0)