Skip to content

Commit 0f1f993

Browse files
committed
feat(go-runner): remove intermediate walltime result allocations
1 parent d785401 commit 0f1f993

3 files changed

Lines changed: 44 additions & 53 deletions

File tree

‎go-runner/src/lib.rs‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
use crate::{builder::BenchmarkPackage, prelude::*};
1+
use crate::{
2+
builder::BenchmarkPackage,
3+
prelude::*,
4+
results::{raw_result::RawResult, walltime_results::WalltimeBenchmark},
5+
};
26
use std::{collections::HashMap, path::Path};
37

48
pub mod builder;
@@ -74,16 +78,13 @@ pub fn run_benchmarks<P: AsRef<Path>>(
7478

7579
// TODO: This should be merged with codspeed-rust/codspeed/walltime_results.rs
7680
pub fn collect_walltime_results(profile_dir: &Path) -> anyhow::Result<()> {
77-
let raw_results = results::raw_result::RawResult::parse_folder(profile_dir)?;
78-
info!("Parsed {} raw results", raw_results.len());
81+
let mut benchmarks_by_pid: HashMap<u32, Vec<WalltimeBenchmark>> = HashMap::new();
7982

80-
let mut benchmarks_by_pid: HashMap<u32, Vec<results::walltime_results::WalltimeBenchmark>> =
81-
HashMap::new();
82-
for raw in raw_results {
83+
for (pid, walltime_result) in RawResult::parse_folder(profile_dir)?.into_iter() {
8384
benchmarks_by_pid
84-
.entry(raw.pid)
85+
.entry(pid)
8586
.or_default()
86-
.push(raw.into_walltime_benchmark());
87+
.push(walltime_result);
8788
}
8889

8990
for (pid, walltime_benchmarks) in benchmarks_by_pid {

‎go-runner/src/results/raw_result.rs‎

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use std::path::Path;
2-
31
use serde::{Deserialize, Serialize};
2+
use std::path::Path;
43

54
use crate::results::walltime_results::WalltimeBenchmark;
65

@@ -15,41 +14,29 @@ pub struct RawResult {
1514
}
1615

1716
impl RawResult {
18-
pub fn parse(content: &str) -> anyhow::Result<Self> {
19-
serde_json::from_str(content)
20-
.map_err(|e| anyhow::anyhow!("Failed to parse raw result: {}", e))
21-
}
22-
23-
pub fn parse_folder<P: AsRef<Path>>(folder: P) -> anyhow::Result<Vec<Self>> {
17+
pub fn parse_folder<P: AsRef<Path>>(
18+
folder: P,
19+
) -> anyhow::Result<Vec<(u32, WalltimeBenchmark)>> {
2420
let glob_pattern = folder.as_ref().join("raw_results").join("*.json");
25-
Ok(glob::glob(&glob_pattern.to_string_lossy())?
21+
let result = glob::glob(&glob_pattern.to_string_lossy())?
2622
.filter_map(Result::ok)
2723
.filter_map(|path| {
28-
let content = std::fs::read_to_string(&path).ok()?;
29-
Self::parse(&content).ok()
24+
let file = std::fs::File::open(&path).ok()?;
25+
let reader = std::io::BufReader::new(file);
26+
let json: Self = serde_json::from_reader(reader).ok()?;
27+
Some((
28+
json.pid,
29+
WalltimeBenchmark::from_runtime_data(
30+
json.name,
31+
json.uri,
32+
&json.codspeed_iters_per_round,
33+
&json.codspeed_time_per_round_ns,
34+
None,
35+
),
36+
))
3037
})
31-
.collect())
32-
}
33-
34-
pub fn into_walltime_benchmark(self) -> WalltimeBenchmark {
35-
let times_per_round_ns = self
36-
.codspeed_time_per_round_ns
37-
.iter()
38-
.map(|t| *t as u128)
39-
.collect::<Vec<_>>();
40-
let iters_per_round = self
41-
.codspeed_iters_per_round
42-
.iter()
43-
.map(|i| *i as u128)
4438
.collect();
45-
46-
WalltimeBenchmark::from_runtime_data(
47-
self.name,
48-
self.uri,
49-
iters_per_round,
50-
times_per_round_ns,
51-
None,
52-
)
39+
Ok(result)
5340
}
5441
}
5542

‎go-runner/src/results/walltime_results.rs‎

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,18 @@ impl WalltimeBenchmark {
5454
pub fn from_runtime_data(
5555
name: String,
5656
uri: String,
57-
iters_per_round: Vec<u128>,
58-
times_per_round_ns: Vec<u128>,
57+
iters_per_round: &[u64],
58+
times_per_round_ns: &[u64],
5959
max_time_ns: Option<u128>,
6060
) -> Self {
61-
let total_time = times_per_round_ns.iter().sum::<u128>() as f64 / 1_000_000_000.0;
61+
let total_time =
62+
times_per_round_ns.iter().map(|&t| t as u128).sum::<u128>() as f64 / 1_000_000_000.0;
6263
let time_per_iteration_per_round_ns: Vec<_> = times_per_round_ns
63-
.into_iter()
64-
.zip(&iters_per_round)
65-
.map(|(time_per_round, iter_per_round)| time_per_round / iter_per_round)
64+
.iter()
65+
.zip(iters_per_round)
66+
.map(|(time_per_round, iter_per_round)| {
67+
*time_per_round as u128 / *iter_per_round as u128
68+
})
6669
.map(|t| t as f64)
6770
.collect::<Vec<f64>>();
6871

@@ -103,8 +106,8 @@ impl WalltimeBenchmark {
103106
let max_ns = data.max();
104107

105108
// TODO(COD-1056): We currently only support single iteration count per round
106-
let iter_per_round =
107-
(iters_per_round.iter().sum::<u128>() / iters_per_round.len() as u128) as u64;
109+
let iter_per_round = (iters_per_round.iter().map(|&t| t as u128).sum::<u128>()
110+
/ iters_per_round.len() as u128) as u64;
108111
let warmup_iters = 0; // FIXME: add warmup detection
109112

110113
let stats = BenchmarkStats {
@@ -178,8 +181,8 @@ mod tests {
178181
let benchmark = WalltimeBenchmark::from_runtime_data(
179182
NAME.to_string(),
180183
URI.to_string(),
181-
vec![1],
182-
vec![42],
184+
&[1],
185+
&[42],
183186
None,
184187
);
185188
assert_eq!(benchmark.stats.stdev_ns, 0.);
@@ -191,13 +194,13 @@ mod tests {
191194
#[test]
192195
fn test_parse_bench_with_variable_iterations() {
193196
let iters_per_round = vec![1, 2, 3, 4, 5, 6];
194-
let total_rounds = iters_per_round.iter().sum::<u128>() as f64;
197+
let total_rounds = iters_per_round.iter().sum::<u64>() as f64;
195198

196199
let benchmark = WalltimeBenchmark::from_runtime_data(
197200
NAME.to_string(),
198201
URI.to_string(),
199-
iters_per_round,
200-
vec![42, 42 * 2, 42 * 3, 42 * 4, 42 * 5, 42 * 6],
202+
&iters_per_round,
203+
&[42, 42 * 2, 42 * 3, 42 * 4, 42 * 5, 42 * 6],
201204
None,
202205
);
203206

0 commit comments

Comments
 (0)