From 6fa4f7187f143d27540308fe8d6a78c1b8f2da30 Mon Sep 17 00:00:00 2001 From: xgreenx Date: Thu, 26 Oct 2023 14:37:44 +0100 Subject: [PATCH 1/3] Subtract the time required to reset the VM from the total time to run the opcode and reset VM. It should produce more clearer estimation for tiny opcodes. --- benches/benches/vm.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/benches/benches/vm.rs b/benches/benches/vm.rs index 5f26e282b2a..cff5a3a1793 100644 --- a/benches/benches/vm.rs +++ b/benches/benches/vm.rs @@ -9,7 +9,6 @@ use criterion::{ BenchmarkGroup, Criterion, }; -use std::time::Duration; use fuel_core_benches::*; use fuel_core_storage::transactional::Transaction; @@ -41,9 +40,17 @@ where db_txn }; - let mut elapsed_time = Duration::default(); + // Measure the total time to revert the VM to the initial state. + // It should always do the same things regardless of the number of + // iterations because we use a `diff` benchmarked during the initialization. + let start = std::time::Instant::now(); + for _ in 0..iters { + vm.reset_vm_state(diff); + } + let time_to_reset = start.elapsed(); + + let start = std::time::Instant::now(); for _ in 0..iters { - let start = std::time::Instant::now(); match instruction { Instruction::CALL(call) => { let (ra, rb, rc, rd) = call.unpack(); @@ -53,13 +60,19 @@ where black_box(vm.instruction(*instruction).unwrap()); } } - elapsed_time += start.elapsed(); vm.reset_vm_state(diff); } + let final_time = start.elapsed().checked_sub(time_to_reset).expect( + "It may overflow when the benchmarks run in an unstable environment. \ + If the hardware is busy during the measuring time to reset the VM, \ + it will produce `time_to_reset` more than the actual time to reset \ + and run the instruction. ", + ); + db_txn.commit().unwrap(); // restore original db *vm.as_mut().database_mut() = original_db; - elapsed_time + final_time }) }); } From 0ca394ba70ab5e3c356fa219afcb0aa30640106a Mon Sep 17 00:00:00 2001 From: xgreenx Date: Thu, 26 Oct 2023 15:09:23 +0100 Subject: [PATCH 2/3] Handle case of the overflow --- benches/benches/vm.rs | 57 +++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/benches/benches/vm.rs b/benches/benches/vm.rs index cff5a3a1793..bfdd58e0b8d 100644 --- a/benches/benches/vm.rs +++ b/benches/benches/vm.rs @@ -40,34 +40,43 @@ where db_txn }; - // Measure the total time to revert the VM to the initial state. - // It should always do the same things regardless of the number of - // iterations because we use a `diff` benchmarked during the initialization. - let start = std::time::Instant::now(); - for _ in 0..iters { - vm.reset_vm_state(diff); - } - let time_to_reset = start.elapsed(); + let final_time; + loop { + // Measure the total time to revert the VM to the initial state. + // It should always do the same things regardless of the number of + // iterations because we use a `diff` from the `VmBenchPrepared` initialization. + let start = std::time::Instant::now(); + for _ in 0..iters { + vm.reset_vm_state(diff); + } + let time_to_reset = start.elapsed(); - let start = std::time::Instant::now(); - for _ in 0..iters { - match instruction { - Instruction::CALL(call) => { - let (ra, rb, rc, rd) = call.unpack(); - vm.prepare_call(ra, rb, rc, rd).unwrap(); - } - _ => { - black_box(vm.instruction(*instruction).unwrap()); + let start = std::time::Instant::now(); + for _ in 0..iters { + match instruction { + Instruction::CALL(call) => { + let (ra, rb, rc, rd) = call.unpack(); + vm.prepare_call(ra, rb, rc, rd).unwrap(); + } + _ => { + black_box(vm.instruction(*instruction).unwrap()); + } } + vm.reset_vm_state(diff); + } + let only_instruction = start.elapsed().checked_sub(time_to_reset); + + // It may overflow when the benchmarks run in an unstable environment. + // If the hardware is busy during the measuring time to reset the VM, + // it will produce `time_to_reset` more than the actual time + // to run the instruction and reset the VM. + if let Some(result) = only_instruction { + final_time = result; + break + } else { + println!("The environment is unstable. Rerunning the benchmark."); } - vm.reset_vm_state(diff); } - let final_time = start.elapsed().checked_sub(time_to_reset).expect( - "It may overflow when the benchmarks run in an unstable environment. \ - If the hardware is busy during the measuring time to reset the VM, \ - it will produce `time_to_reset` more than the actual time to reset \ - and run the instruction. ", - ); db_txn.commit().unwrap(); // restore original db From 0e9aa0e912344f560835030c0c3d3719d44c0408 Mon Sep 17 00:00:00 2001 From: xgreenx Date: Thu, 26 Oct 2023 20:48:17 +0100 Subject: [PATCH 3/3] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e437d999d47..5b6ca4915da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). Description of the upcoming release here. ### Added +- [#1457](https://github.com/FuelLabs/fuel-core/pull/1457): Fixing incorrect measurement for fast(µs) opcodes. - [#1449](https://github.com/FuelLabs/fuel-core/pull/1449): fix coin pagination in e2e test client - [#1447](https://github.com/FuelLabs/fuel-core/pull/1447): Add timeout for continuous e2e tests - [#1444](https://github.com/FuelLabs/fuel-core/pull/1444): Add "sanity" benchmarks for memory opcodes.