Skip to content

Commit 11a0394

Browse files
committed
feat(divan): placeholder implementation of counter
1 parent 8923641 commit 11a0394

File tree

6 files changed

+353
-0
lines changed

6 files changed

+353
-0
lines changed

crates/divan_compat/examples/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,7 @@ harness = false
4040
[[bench]]
4141
name = "the_algorithms"
4242
harness = false
43+
44+
[[bench]]
45+
name = "counters"
46+
harness = false
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
//! Example benchmarks demonstrating divan counter usage
2+
//!
3+
//! This file shows how to use different types of counters with divan:
4+
//! - BytesCount: for measuring throughput in bytes
5+
//! - ItemsCount: for counting processed items
6+
//! - CharsCount: for counting processed characters
7+
//! - CyclesCount: for counting processing cycles
8+
9+
use divan::{counter::*, AllocProfiler, Bencher};
10+
11+
#[global_allocator]
12+
static ALLOC: AllocProfiler = AllocProfiler::system();
13+
14+
fn main() {
15+
divan::main();
16+
}
17+
18+
/// Example data for benchmarks
19+
const SAMPLE_DATA: &[i32] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
20+
const SAMPLE_TEXT: &str = "Hello, world! This is a sample string for benchmarking.";
21+
22+
mod bytes_counter_examples {
23+
use super::*;
24+
25+
#[divan::bench]
26+
fn vec_copy_with_bytes_counter(bencher: Bencher) {
27+
let data = SAMPLE_DATA;
28+
let bytes = BytesCount::of_slice(data);
29+
30+
bencher
31+
.counter(bytes)
32+
.bench(|| -> Vec<i32> { divan::black_box(data).to_vec() });
33+
}
34+
35+
#[divan::bench]
36+
fn string_copy_with_bytes_counter(bencher: Bencher) {
37+
let text = SAMPLE_TEXT;
38+
let bytes = BytesCount::of_str(text);
39+
40+
bencher
41+
.counter(bytes)
42+
.bench(|| -> String { divan::black_box(text).to_owned() });
43+
}
44+
45+
#[divan::bench]
46+
fn slice_into_vec_with_bytes(bencher: Bencher) {
47+
let ints = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
48+
let bytes = BytesCount::of_slice(ints);
49+
50+
bencher
51+
.counter(bytes)
52+
.bench(|| -> Vec<i32> { divan::black_box(ints).into() });
53+
}
54+
}
55+
56+
mod items_counter_examples {
57+
use super::*;
58+
59+
#[divan::bench]
60+
fn process_items_with_counter(bencher: Bencher) {
61+
let data = SAMPLE_DATA;
62+
let items = ItemsCount::new(data.len());
63+
64+
bencher
65+
.counter(items)
66+
.bench(|| -> Vec<i32> { divan::black_box(data).iter().map(|x| x * 2).collect() });
67+
}
68+
69+
#[divan::bench]
70+
fn filter_items_with_counter(bencher: Bencher) {
71+
let data = (1..=100).collect::<Vec<_>>();
72+
let items = ItemsCount::new(data.len());
73+
74+
bencher.counter(items).bench(|| -> Vec<i32> {
75+
divan::black_box(&data)
76+
.iter()
77+
.filter(|&&x| x % 2 == 0)
78+
.copied()
79+
.collect()
80+
});
81+
}
82+
}
83+
84+
mod chars_counter_examples {
85+
use super::*;
86+
87+
#[divan::bench]
88+
fn count_chars_in_string(bencher: Bencher) {
89+
let text = SAMPLE_TEXT;
90+
let chars = CharsCount::of_str(text);
91+
92+
bencher
93+
.counter(chars)
94+
.bench(|| -> usize { divan::black_box(text).chars().count() });
95+
}
96+
97+
#[divan::bench]
98+
fn uppercase_chars_with_counter(bencher: Bencher) {
99+
let text = "hello world with unicode: café naïve résumé";
100+
let chars = CharsCount::of_str(text);
101+
102+
bencher
103+
.counter(chars)
104+
.bench(|| -> String { divan::black_box(text).to_uppercase() });
105+
}
106+
}
107+
108+
mod cycles_counter_examples {
109+
use super::*;
110+
111+
#[divan::bench]
112+
fn simulated_processing_cycles(bencher: Bencher) {
113+
// Simulate processing 1000 "cycles" of work
114+
let cycles = CyclesCount::new(1000u32);
115+
116+
bencher.counter(cycles).bench(|| {
117+
// Simulate some work that processes 1000 cycles
118+
let mut sum = 0u64;
119+
for i in 0..1000 {
120+
sum = sum.wrapping_add(divan::black_box(i));
121+
}
122+
sum
123+
});
124+
}
125+
126+
#[divan::bench]
127+
fn hash_computation_cycles(bencher: Bencher) {
128+
let data = SAMPLE_DATA;
129+
// Treat each hash operation as processing N cycles where N = data length
130+
let cycles = CyclesCount::new(data.len());
131+
132+
bencher.counter(cycles).bench(|| -> u64 {
133+
use std::collections::hash_map::DefaultHasher;
134+
use std::hash::{Hash, Hasher};
135+
136+
let mut hasher = DefaultHasher::new();
137+
divan::black_box(data).hash(&mut hasher);
138+
hasher.finish()
139+
});
140+
}
141+
}
142+
143+
mod multiple_counters_examples {
144+
use super::*;
145+
146+
#[divan::bench(counters = [BytesCount::of_slice(SAMPLE_DATA), ItemsCount::new(SAMPLE_DATA.len())])]
147+
fn process_with_multiple_counters() -> Vec<i32> {
148+
SAMPLE_DATA.iter().map(|x| x * x).collect()
149+
}
150+
151+
#[divan::bench]
152+
fn string_processing_multi_counter(bencher: Bencher) {
153+
let text = "Processing this text with multiple counters";
154+
155+
bencher
156+
.counter(BytesCount::of_str(text))
157+
.counter(CharsCount::of_str(text))
158+
.bench(|| -> Vec<char> { divan::black_box(text).chars().collect() });
159+
}
160+
}

crates/divan_compat/macros/src/args.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ impl AttrOptions {
4545
// These arguments are ignored for codspeed runs
4646
meta.value()?.parse::<Expr>()?; // Discard the value
4747
}
48+
"counters" => {
49+
// Counters are not yet supported, but we parse them to avoid errors
50+
eprintln!(
51+
"Warning: Counter feature is not yet supported by codspeed-divan-compat"
52+
);
53+
meta.value()?.parse::<Expr>()?; // Discard the value
54+
}
4855
_ => {
4956
let path = meta.path.clone();
5057
let parsed_meta = if meta.input.is_empty() {

crates/divan_compat/src/compat/bench/mod.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,27 @@ impl<'a, 'b> Bencher<'a, 'b> {
5151
_marker: self._marker,
5252
}
5353
}
54+
55+
/// Add a counter to this benchmark (placeholder implementation).
56+
///
57+
/// Note: Counters are not yet supported by codspeed-divan-compat.
58+
/// This method is provided for API compatibility but does not affect benchmarking.
59+
pub fn counter<C>(self, _counter: C) -> Self {
60+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
61+
self
62+
}
63+
64+
/// Add a counter based on input to this benchmark (placeholder implementation).
65+
///
66+
/// Note: Counters are not yet supported by codspeed-divan-compat.
67+
/// This method is provided for API compatibility but does not affect benchmarking.
68+
pub fn input_counter<C, F>(self, _counter_fn: F) -> Self
69+
where
70+
F: Fn() -> C,
71+
{
72+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
73+
self
74+
}
5475
}
5576

5677
impl<'a, 'b> Bencher<'a, 'b> {
@@ -73,6 +94,26 @@ impl<'a, 'b, I, GenI> Bencher<'a, 'b, BencherConfig<GenI>>
7394
where
7495
GenI: FnMut() -> I,
7596
{
97+
/// Add a counter to this benchmark (placeholder implementation).
98+
///
99+
/// Note: Counters are not yet supported by codspeed-divan-compat.
100+
/// This method is provided for API compatibility but does not affect benchmarking.
101+
pub fn counter<C>(self, _counter: C) -> Self {
102+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
103+
self
104+
}
105+
106+
/// Add a counter based on input to this benchmark (placeholder implementation).
107+
///
108+
/// Note: Counters are not yet supported by codspeed-divan-compat.
109+
/// This method is provided for API compatibility but does not affect benchmarking.
110+
pub fn input_counter<C, F>(self, _counter_fn: F) -> Self
111+
where
112+
F: Fn(&I) -> C,
113+
{
114+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
115+
self
116+
}
76117
pub fn bench_values<O, B>(self, benched: B)
77118
where
78119
B: Fn(I) -> O + Sync,

crates/divan_compat/src/compat/bench/options.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,10 @@ pub struct BenchOptions {
1010
/// This may be set within the attribute or with a separate
1111
/// [`#[ignore]`](https://doc.rust-lang.org/reference/attributes/testing.html#the-ignore-attribute).
1212
pub ignore: Option<bool>,
13+
14+
/// Counters to be used with this benchmark.
15+
///
16+
/// Note: Counters are not yet supported by codspeed-divan-compat.
17+
/// This field is provided for API compatibility but does not affect benchmarking.
18+
pub counters: Option<Vec<String>>,
1319
}

crates/divan_compat/src/compat/mod.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,141 @@ mod uri;
2020
mod util;
2121

2222
pub use bench::*;
23+
24+
// Counter types (placeholder implementations)
25+
pub mod counter {
26+
/// Process N bytes.
27+
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
28+
pub struct BytesCount {
29+
count: u64,
30+
}
31+
32+
/// Process N [`char`s](char).
33+
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
34+
pub struct CharsCount {
35+
count: u64,
36+
}
37+
38+
/// Process N cycles, displayed as Hertz.
39+
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
40+
pub struct CyclesCount {
41+
count: u64,
42+
}
43+
44+
/// Process N items.
45+
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
46+
pub struct ItemsCount {
47+
count: u64,
48+
}
49+
50+
impl BytesCount {
51+
/// Count N bytes.
52+
#[inline]
53+
pub fn new<N>(count: N) -> Self
54+
where
55+
N: TryInto<u64>,
56+
N::Error: std::fmt::Debug,
57+
{
58+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
59+
Self {
60+
count: count.try_into().unwrap(),
61+
}
62+
}
63+
64+
/// Counts the size of a type with [`size_of`].
65+
#[inline]
66+
pub fn of<T>() -> Self {
67+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
68+
Self {
69+
count: std::mem::size_of::<T>() as u64,
70+
}
71+
}
72+
73+
/// Counts the size of multiple instances of a type with [`size_of`].
74+
#[inline]
75+
pub fn of_many<T>(n: usize) -> Self {
76+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
77+
Self {
78+
count: (std::mem::size_of::<T>() * n) as u64,
79+
}
80+
}
81+
82+
/// Counts the size of a value with [`size_of_val`].
83+
#[inline]
84+
pub fn of_val<T: ?Sized>(val: &T) -> Self {
85+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
86+
Self {
87+
count: std::mem::size_of_val(val) as u64,
88+
}
89+
}
90+
91+
/// Counts the bytes of a [`&str`].
92+
#[inline]
93+
pub fn of_str<S: ?Sized + AsRef<str>>(s: &S) -> Self {
94+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
95+
Self::of_val(s.as_ref())
96+
}
97+
98+
/// Counts the bytes of a [slice](prim@slice).
99+
#[inline]
100+
pub fn of_slice<T, S: ?Sized + AsRef<[T]>>(s: &S) -> Self {
101+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
102+
Self::of_val(s.as_ref())
103+
}
104+
}
105+
106+
impl CharsCount {
107+
/// Count N [`char`s](char).
108+
#[inline]
109+
pub fn new<N>(count: N) -> Self
110+
where
111+
N: TryInto<u64>,
112+
N::Error: std::fmt::Debug,
113+
{
114+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
115+
Self {
116+
count: count.try_into().unwrap(),
117+
}
118+
}
119+
120+
/// Counts the [`char`s](prim@char) of a [`&str`](prim@str).
121+
#[inline]
122+
pub fn of_str<S: ?Sized + AsRef<str>>(s: &S) -> Self {
123+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
124+
Self::new(s.as_ref().chars().count() as u64)
125+
}
126+
}
127+
128+
impl CyclesCount {
129+
/// Count N cycles.
130+
#[inline]
131+
pub fn new<N>(count: N) -> Self
132+
where
133+
N: TryInto<u64>,
134+
N::Error: std::fmt::Debug,
135+
{
136+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
137+
Self {
138+
count: count.try_into().unwrap(),
139+
}
140+
}
141+
}
142+
143+
impl ItemsCount {
144+
/// Count N items.
145+
#[inline]
146+
pub fn new<N>(count: N) -> Self
147+
where
148+
N: TryInto<u64>,
149+
N::Error: std::fmt::Debug,
150+
{
151+
eprintln!("Warning: Counter feature is not yet supported by codspeed-divan-compat");
152+
Self {
153+
count: count.try_into().unwrap(),
154+
}
155+
}
156+
}
157+
}
23158
use codspeed::codspeed::CodSpeed;
24159
use config::Filter;
25160
use entry::AnyBenchEntry;

0 commit comments

Comments
 (0)