Skip to content

Commit 2ecde6a

Browse files
authored
Fixing incorrect measurement for fast(µs) opcodes (#1457)
Closes #1431 In the case of super-fast opcodes(< than 1 µs), the `elapse` method is not accurate enough, which leads to unstable results from benchmarks. The change aims to stabilize the results from measurements by subtracting the time required to reset the VM from the total time of the benchmark.
1 parent df673ea commit 2ecde6a

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99
Description of the upcoming release here.
1010

1111
### Added
12+
- [#1457](https://github.com/FuelLabs/fuel-core/pull/1457): Fixing incorrect measurement for fast(µs) opcodes.
1213
- [#1449](https://github.com/FuelLabs/fuel-core/pull/1449): fix coin pagination in e2e test client
1314
- [#1447](https://github.com/FuelLabs/fuel-core/pull/1447): Add timeout for continuous e2e tests
1415
- [#1444](https://github.com/FuelLabs/fuel-core/pull/1444): Add "sanity" benchmarks for memory opcodes.

benches/benches/vm.rs

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use criterion::{
99
BenchmarkGroup,
1010
Criterion,
1111
};
12-
use std::time::Duration;
1312

1413
use fuel_core_benches::*;
1514
use fuel_core_storage::transactional::Transaction;
@@ -41,25 +40,48 @@ where
4140
db_txn
4241
};
4342

44-
let mut elapsed_time = Duration::default();
45-
for _ in 0..iters {
43+
let final_time;
44+
loop {
45+
// Measure the total time to revert the VM to the initial state.
46+
// It should always do the same things regardless of the number of
47+
// iterations because we use a `diff` from the `VmBenchPrepared` initialization.
4648
let start = std::time::Instant::now();
47-
match instruction {
48-
Instruction::CALL(call) => {
49-
let (ra, rb, rc, rd) = call.unpack();
50-
vm.prepare_call(ra, rb, rc, rd).unwrap();
51-
}
52-
_ => {
53-
black_box(vm.instruction(*instruction).unwrap());
49+
for _ in 0..iters {
50+
vm.reset_vm_state(diff);
51+
}
52+
let time_to_reset = start.elapsed();
53+
54+
let start = std::time::Instant::now();
55+
for _ in 0..iters {
56+
match instruction {
57+
Instruction::CALL(call) => {
58+
let (ra, rb, rc, rd) = call.unpack();
59+
vm.prepare_call(ra, rb, rc, rd).unwrap();
60+
}
61+
_ => {
62+
black_box(vm.instruction(*instruction).unwrap());
63+
}
5464
}
65+
vm.reset_vm_state(diff);
66+
}
67+
let only_instruction = start.elapsed().checked_sub(time_to_reset);
68+
69+
// It may overflow when the benchmarks run in an unstable environment.
70+
// If the hardware is busy during the measuring time to reset the VM,
71+
// it will produce `time_to_reset` more than the actual time
72+
// to run the instruction and reset the VM.
73+
if let Some(result) = only_instruction {
74+
final_time = result;
75+
break
76+
} else {
77+
println!("The environment is unstable. Rerunning the benchmark.");
5578
}
56-
elapsed_time += start.elapsed();
57-
vm.reset_vm_state(diff);
5879
}
80+
5981
db_txn.commit().unwrap();
6082
// restore original db
6183
*vm.as_mut().database_mut() = original_db;
62-
elapsed_time
84+
final_time
6385
})
6486
});
6587
}

0 commit comments

Comments
 (0)