mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-12 22:11:01 +00:00
Implement Yul to LLVM IR compilation benchmarks (#407)
# Description Closes [#404](https://github.com/paritytech/revive/issues/404) Adds compilation time benchmarks for: * Parsing of Yul source code -> AST Object * Lowering of AST Object -> LLVM IR (unoptimized) The benchmarks can be run from the root via: ```sh # Run all benchmarks in the revive-yul crate (parsing + lowering) make bench-yul ``` HTML reports will be generated under `target/criterion`, and a summary of the results at [crates/yul/BENCHMARKS_PARSE_M4PRO.md](https://github.com/paritytech/revive/blob/lj/compilation-benchmarks-yul/crates/yul/BENCHMARKS_PARSE_M4PRO.md) and [crates/yul/BENCHMARKS_LOWER_M4PRO.md](https://github.com/paritytech/revive/blob/lj/compilation-benchmarks-yul/crates/yul/BENCHMARKS_LOWER_M4PRO.md) (currently from running on a Mac M4 Pro). --------- Co-authored-by: xermicus <cyrill@parity.io>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
# Benchmarks
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Benchmark Results](#benchmark-results)
|
||||
- [Baseline](#baseline)
|
||||
- [ERC20](#erc20)
|
||||
- [SHA1](#sha1)
|
||||
- [Storage](#storage)
|
||||
- [Transfer](#transfer)
|
||||
|
||||
## Benchmark Results
|
||||
|
||||
### Baseline
|
||||
|
||||
| | `lower` |
|
||||
|:-------|:-------------------------- |
|
||||
| | `110.18 us` (✅ **1.00x**) |
|
||||
|
||||
### ERC20
|
||||
|
||||
| | `lower` |
|
||||
|:-------|:-------------------------- |
|
||||
| | `623.57 us` (✅ **1.00x**) |
|
||||
|
||||
### SHA1
|
||||
|
||||
| | `lower` |
|
||||
|:-------|:-------------------------- |
|
||||
| | `357.61 us` (✅ **1.00x**) |
|
||||
|
||||
### Storage
|
||||
|
||||
| | `lower` |
|
||||
|:-------|:-------------------------- |
|
||||
| | `161.24 us` (✅ **1.00x**) |
|
||||
|
||||
### Transfer
|
||||
|
||||
| | `lower` |
|
||||
|:-------|:-------------------------- |
|
||||
| | `162.35 us` (✅ **1.00x**) |
|
||||
|
||||
---
|
||||
Made with [criterion-table](https://github.com/nu11ptr/criterion-table)
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# Benchmarks
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Benchmark Results](#benchmark-results)
|
||||
- [Baseline](#baseline)
|
||||
- [ERC20](#erc20)
|
||||
- [SHA1](#sha1)
|
||||
- [Storage](#storage)
|
||||
- [Transfer](#transfer)
|
||||
|
||||
## Benchmark Results
|
||||
|
||||
### Baseline
|
||||
|
||||
| | `parse` |
|
||||
|:-------|:------------------------ |
|
||||
| | `8.20 us` (✅ **1.00x**) |
|
||||
|
||||
### ERC20
|
||||
|
||||
| | `parse` |
|
||||
|:-------|:-------------------------- |
|
||||
| | `155.02 us` (✅ **1.00x**) |
|
||||
|
||||
### SHA1
|
||||
|
||||
| | `parse` |
|
||||
|:-------|:------------------------- |
|
||||
| | `74.76 us` (✅ **1.00x**) |
|
||||
|
||||
### Storage
|
||||
|
||||
| | `parse` |
|
||||
|:-------|:------------------------- |
|
||||
| | `17.05 us` (✅ **1.00x**) |
|
||||
|
||||
### Transfer
|
||||
|
||||
| | `parse` |
|
||||
|:-------|:------------------------- |
|
||||
| | `19.37 us` (✅ **1.00x**) |
|
||||
|
||||
---
|
||||
Made with [criterion-table](https://github.com/nu11ptr/criterion-table)
|
||||
|
||||
@@ -18,3 +18,16 @@ thiserror = { workspace = true }
|
||||
|
||||
revive-common = { workspace = true }
|
||||
revive-llvm-context = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
alloy-primitives = { workspace = true }
|
||||
criterion = { workspace = true }
|
||||
revive-integration = { workspace = true }
|
||||
|
||||
[[bench]]
|
||||
name = "parse"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "lower"
|
||||
harness = false
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use alloy_primitives::U256;
|
||||
use criterion::{
|
||||
criterion_group, criterion_main,
|
||||
measurement::{Measurement, WallTime},
|
||||
BatchSize, BenchmarkGroup, Criterion,
|
||||
};
|
||||
use inkwell::context::Context as InkwellContext;
|
||||
use revive_integration::cases::Contract;
|
||||
use revive_llvm_context::{
|
||||
initialize_llvm, OptimizerSettings, PolkaVMContext, PolkaVMTarget, PolkaVMWriteLLVM,
|
||||
};
|
||||
use revive_yul::{lexer::Lexer, parser::statement::object::Object};
|
||||
|
||||
/// The function under test lowers the Yul `Object` into unoptimized LLVM IR.
|
||||
fn lower(mut ast: Object, mut llvm_context: PolkaVMContext) {
|
||||
ast.declare(&mut llvm_context)
|
||||
.expect("the AST should be valid");
|
||||
ast.into_llvm(&mut llvm_context)
|
||||
.expect("the AST should lower to LLVM IR");
|
||||
}
|
||||
|
||||
fn parse(source_code: &str) -> Object {
|
||||
let mut lexer = Lexer::new(source_code.to_owned());
|
||||
Object::parse(&mut lexer, None).expect("the Yul source should parse")
|
||||
}
|
||||
|
||||
fn group<'error, M>(c: &'error mut Criterion<M>, group_name: &str) -> BenchmarkGroup<'error, M>
|
||||
where
|
||||
M: Measurement,
|
||||
{
|
||||
c.benchmark_group(group_name)
|
||||
}
|
||||
|
||||
fn bench<F>(mut group: BenchmarkGroup<'_, WallTime>, contract: F)
|
||||
where
|
||||
F: Fn() -> Contract,
|
||||
{
|
||||
let ast = parse(&contract().yul);
|
||||
let llvm = InkwellContext::create();
|
||||
// The optimizer settings will not affect the benchmarks since we're
|
||||
// not running the optimization passes.
|
||||
let optimizer_settings = OptimizerSettings::none();
|
||||
|
||||
initialize_llvm(PolkaVMTarget::PVM, "resolc", Default::default());
|
||||
|
||||
group
|
||||
.sample_size(90)
|
||||
.measurement_time(Duration::from_secs(6));
|
||||
|
||||
group.bench_function("lower", |b| {
|
||||
b.iter_batched(
|
||||
|| {
|
||||
(
|
||||
ast.clone(),
|
||||
PolkaVMContext::new_dummy(&llvm, optimizer_settings.to_owned()),
|
||||
)
|
||||
},
|
||||
|(ast, llvm_context)| lower(ast, llvm_context),
|
||||
BatchSize::SmallInput,
|
||||
);
|
||||
});
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
fn bench_baseline(c: &mut Criterion) {
|
||||
bench(group(c, "Baseline"), Contract::baseline);
|
||||
}
|
||||
|
||||
fn bench_erc20(c: &mut Criterion) {
|
||||
bench(group(c, "ERC20"), Contract::erc20);
|
||||
}
|
||||
|
||||
fn bench_sha1(c: &mut Criterion) {
|
||||
bench(group(c, "SHA1"), || Contract::sha1(vec![0xff].into()));
|
||||
}
|
||||
|
||||
fn bench_storage(c: &mut Criterion) {
|
||||
bench(group(c, "Storage"), || {
|
||||
Contract::storage_transient(U256::from(0))
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_transfer(c: &mut Criterion) {
|
||||
bench(group(c, "Transfer"), || {
|
||||
Contract::transfer_self(U256::from(0))
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
name = benches_lower;
|
||||
config = Criterion::default();
|
||||
targets =
|
||||
bench_baseline,
|
||||
bench_erc20,
|
||||
bench_sha1,
|
||||
bench_storage,
|
||||
bench_transfer,
|
||||
);
|
||||
criterion_main!(benches_lower);
|
||||
@@ -0,0 +1,72 @@
|
||||
use alloy_primitives::U256;
|
||||
use criterion::{
|
||||
criterion_group, criterion_main,
|
||||
measurement::{Measurement, WallTime},
|
||||
BenchmarkGroup, Criterion,
|
||||
};
|
||||
use revive_integration::cases::Contract;
|
||||
use revive_yul::{lexer::Lexer, parser::statement::object::Object};
|
||||
|
||||
/// The function under test parses the Yul `source_code`.
|
||||
fn parse(source_code: &str) {
|
||||
let mut lexer = Lexer::new(source_code.to_owned());
|
||||
Object::parse(&mut lexer, None).expect("the Yul source should parse");
|
||||
}
|
||||
|
||||
fn group<'error, M>(c: &'error mut Criterion<M>, group_name: &str) -> BenchmarkGroup<'error, M>
|
||||
where
|
||||
M: Measurement,
|
||||
{
|
||||
c.benchmark_group(group_name)
|
||||
}
|
||||
|
||||
fn bench<F>(mut group: BenchmarkGroup<'_, WallTime>, contract: F)
|
||||
where
|
||||
F: Fn() -> Contract,
|
||||
{
|
||||
let source_code = contract().yul;
|
||||
|
||||
group.sample_size(200);
|
||||
|
||||
group.bench_function("parse", |b| {
|
||||
b.iter(|| parse(&source_code));
|
||||
});
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
fn bench_baseline(c: &mut Criterion) {
|
||||
bench(group(c, "Baseline"), Contract::baseline);
|
||||
}
|
||||
|
||||
fn bench_erc20(c: &mut Criterion) {
|
||||
bench(group(c, "ERC20"), Contract::erc20);
|
||||
}
|
||||
|
||||
fn bench_sha1(c: &mut Criterion) {
|
||||
bench(group(c, "SHA1"), || Contract::sha1(vec![0xff].into()));
|
||||
}
|
||||
|
||||
fn bench_storage(c: &mut Criterion) {
|
||||
bench(group(c, "Storage"), || {
|
||||
Contract::storage_transient(U256::from(0))
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_transfer(c: &mut Criterion) {
|
||||
bench(group(c, "Transfer"), || {
|
||||
Contract::transfer_self(U256::from(0))
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
name = benches_parse;
|
||||
config = Criterion::default();
|
||||
targets =
|
||||
bench_baseline,
|
||||
bench_erc20,
|
||||
bench_sha1,
|
||||
bench_storage,
|
||||
bench_transfer,
|
||||
);
|
||||
criterion_main!(benches_parse);
|
||||
Reference in New Issue
Block a user