generation of real benchmark functions for benchmarking v2 (#13224)

* function generation with _name working, need to modify signature

* WIP

* support custom BenchmarkResult<T> type

* full support for BenchmarkResult<T> on benchmark function defs

* support () return type for benchmark function defs that don't use ?

* uncomment

* fix where clause handling

* fix benchmark function call bodies

* proper parsing of return type

* add UI tests for bad return type

* fix detection of missing last_stmt with defined return type

* UI tests covering missing last_stmt

* properly detect and complain about empty benchmark function defs

* fix missing Comma in Result<T, BenchmarkError> parsing + test

* add additional UI test

* allow complex path for BenchmarkResult and BenchmarkError in fn defs

* add UI tests covering complex path for BenchmarkResult, BenchmarkError

* retain doc comments and attributes

* also add attributes to struct

* add docs for benchmark function definition support

* fix imports on benchmark example

* fix issue with unused variables in extrinsic call fn def

* fix up docs

* remove support for v2::BenchmarkResult because it was confusing

* fix typo

* remove ability to use custom T for Result<T, BenchmarkError> in v2

* use missing call error instead of empty_fn()

* remove unneeded match statement

* Add a proper QED

Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>

* fix other QED

Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>

* cargo fmt

* add an explicit error for non TypePath as return type

* tweak error warning and add a UI test for non TypePath return

* remove comment

* add docs about T and I generic params

* improve docs referring to section "below"

* pull out return type checking logic into its own function

* pull out params parsing into its own function

* pull out call_def parsing into its own function

* add doc comment for missing_call()

* replace spaces with tabs

* add a result-based example to the benchmarking examples

---------

Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
This commit is contained in:
Sam Johnson
2023-02-22 09:09:11 -05:00
committed by GitHub
parent af25310eb0
commit 55ff791d80
26 changed files with 604 additions and 98 deletions
@@ -0,0 +1,19 @@
use frame_benchmarking::v2::*;
#[allow(unused_imports)]
use frame_support_test::Config;
#[benchmarks]
mod benches {
use super::*;
#[benchmark]
fn bench() -> Result<(), BenchmarkException> {
let a = 2 + 2;
#[block]
{}
assert_eq!(a, 4);
Ok(())
}
}
fn main() {}
@@ -0,0 +1,5 @@
error: expected `BenchmarkError`
--> tests/benchmark_ui/bad_return_non_benchmark_err.rs:10:27
|
10 | fn bench() -> Result<(), BenchmarkException> {
| ^^^^^^^^^^^^^^^^^^
@@ -0,0 +1,17 @@
use frame_benchmarking::v2::*;
#[allow(unused_imports)]
use frame_support_test::Config;
#[benchmarks]
mod benchmarks {
use super::*;
#[benchmark]
fn bench() -> (String, u32) {
#[block]
{}
(String::from("hey"), 23)
}
}
fn main() {}
@@ -0,0 +1,5 @@
error: Only `Result<(), BenchmarkError>` or a blank return type is allowed on benchmark function definitions
--> tests/benchmark_ui/bad_return_non_type_path.rs:10:16
|
10 | fn bench() -> (String, u32) {
| ^^^^^^^^^^^^^
@@ -0,0 +1,15 @@
use frame_benchmarking::v2::*;
#[allow(unused_imports)]
use frame_support_test::Config;
#[benchmarks]
mod benchmarks {
#[benchmark]
fn bench() -> Result<u32, BenchmarkError> {
#[block]
{}
Ok(10)
}
}
fn main() {}
@@ -0,0 +1,5 @@
error: expected `()`
--> tests/benchmark_ui/bad_return_non_unit_t.rs:8:23
|
8 | fn bench() -> Result<u32, BenchmarkError> {
| ^^^
@@ -0,0 +1,22 @@
use frame_benchmarking::v2::*;
#[allow(unused_imports)]
use frame_support_test::Config;
#[benchmarks]
mod benches {
use super::*;
fn something() -> Result<(), BenchmarkError> {
Ok(())
}
#[benchmark]
fn bench() {
something()?;
#[block]
{}
assert_eq!(2 + 2, 4);
}
}
fn main() {}
@@ -0,0 +1,10 @@
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
--> tests/benchmark_ui/bad_return_type_blank_with_question.rs:15:14
|
5 | #[benchmarks]
| ------------- this function should return `Result` or `Option` to accept `?`
...
15 | something()?;
| ^ cannot use the `?` operator in a function that returns `()`
|
= help: the trait `FromResidual<Result<std::convert::Infallible, frame_benchmarking::BenchmarkError>>` is not implemented for `()`
@@ -0,0 +1,16 @@
use frame_benchmarking::v2::*;
#[allow(unused_imports)]
use frame_support_test::Config;
#[benchmarks]
mod benches {
use super::*;
#[benchmark]
fn bench() -> Result<(), BenchmarkError> {
#[block]
{}
}
}
fn main() {}
@@ -0,0 +1,9 @@
error: Benchmark `#[block]` or `#[extrinsic_call]` item cannot be the last statement of your benchmark function definition if you have defined a return type. You should return something compatible with Result<(), BenchmarkError> (i.e. `Ok(())`) as the last statement or change your signature to a blank return type.
--> tests/benchmark_ui/bad_return_type_no_last_stmt.rs:10:43
|
10 | fn bench() -> Result<(), BenchmarkError> {
| ______________________________________________^
11 | | #[block]
12 | | {}
13 | | }
| |_____^
@@ -0,0 +1,19 @@
use frame_benchmarking::v2::*;
#[allow(unused_imports)]
use frame_support_test::Config;
#[benchmarks]
mod benches {
use super::*;
#[benchmark]
fn bench(y: Linear<1, 2>) -> String {
let a = 2 + 2;
#[block]
{}
assert_eq!(a, 4);
String::from("test")
}
}
fn main() {}
@@ -0,0 +1,5 @@
error: expected `Result`
--> tests/benchmark_ui/bad_return_type_non_result.rs:10:31
|
10 | fn bench(y: Linear<1, 2>) -> String {
| ^^^^^^
@@ -0,0 +1,18 @@
use frame_benchmarking::v2::*;
#[allow(unused_imports)]
use frame_support_test::Config;
#[benchmarks]
mod benches {
use super::*;
#[benchmark]
fn bench() -> Option<BenchmarkError> {
#[block]
{}
assert_eq!(2 + 2, 4);
None
}
}
fn main() {}
@@ -0,0 +1,5 @@
error: expected `Result`
--> tests/benchmark_ui/bad_return_type_option.rs:10:16
|
10 | fn bench() -> Option<BenchmarkError> {
| ^^^^^^
@@ -0,0 +1,13 @@
use frame_benchmarking::v2::*;
#[allow(unused_imports)]
use frame_support_test::Config;
#[benchmarks]
mod benches {
use super::*;
#[benchmark]
fn bench() {}
}
fn main() {}
@@ -0,0 +1,5 @@
error: No valid #[extrinsic_call] or #[block] annotation could be found in benchmark function body.
--> tests/benchmark_ui/empty_function.rs:10:13
|
10 | fn bench() {}
| ^^
@@ -7,7 +7,9 @@ mod benches {
use super::*;
#[benchmark]
fn bench() {}
fn bench() {
assert_eq!(2 + 2, 4);
}
}
fn main() {}
@@ -1,5 +1,8 @@
error: No valid #[extrinsic_call] or #[block] annotation could be found in benchmark function body.
--> tests/benchmark_ui/missing_call.rs:10:13
|
10 | fn bench() {}
| ^^
10 | fn bench() {
| ________________^
11 | | assert_eq!(2 + 2, 4);
12 | | }
| |_____^
@@ -0,0 +1,17 @@
use frame_benchmarking::v2::*;
#[allow(unused_imports)]
use frame_support_test::Config;
#[benchmarks]
mod benches {
use super::*;
#[benchmark]
fn bench() -> Result<(), frame_benchmarking::v2::BenchmarkError> {
#[block]
{}
Ok(())
}
}
fn main() {}
@@ -0,0 +1,16 @@
use frame_benchmarking::v2::*;
#[allow(unused_imports)]
use frame_support_test::Config;
#[benchmarks]
mod benches {
use super::*;
#[benchmark]
fn bench() {
#[block]
{}
}
}
fn main() {}
@@ -0,0 +1,17 @@
use frame_benchmarking::v2::*;
#[allow(unused_imports)]
use frame_support_test::Config;
#[benchmarks]
mod benches {
use super::*;
#[benchmark]
fn bench() -> Result<(), frame_benchmarking::v2::BenchmarkError> {
#[block]
{}
Ok(())
}
}
fn main() {}
@@ -0,0 +1,18 @@
use frame_benchmarking::v2::*;
use frame_support_test::Config;
#[benchmarks]
mod benches {
use super::*;
#[benchmark]
fn bench() -> Result<(), BenchmarkError> {
let a = 2 + 2;
#[block]
{}
assert_eq!(a, 4);
Ok(())
}
}
fn main() {}