iai_callgrind/lib_bench.rs
1use std::ffi::OsString;
2
3use derive_more::AsRef;
4use iai_callgrind_macros::IntoInner;
5
6use crate::{internal, EntryPoint};
7
8/// The main configuration of a library benchmark.
9///
10/// See [`LibraryBenchmarkConfig::callgrind_args`] for more details.
11///
12/// # Examples
13///
14/// ```rust
15/// # use iai_callgrind::{library_benchmark, library_benchmark_group};
16/// use iai_callgrind::{LibraryBenchmarkConfig, main};
17/// # #[library_benchmark]
18/// # fn some_func() {}
19/// # library_benchmark_group!(name = some_group; benchmarks = some_func);
20/// # fn main() {
21/// main!(
22/// config = LibraryBenchmarkConfig::default()
23/// .callgrind_args(["toggle-collect=something"]);
24/// library_benchmark_groups = some_group
25/// );
26/// # }
27/// ```
28#[derive(Debug, Default, IntoInner, AsRef, Clone)]
29pub struct LibraryBenchmarkConfig(internal::InternalLibraryBenchmarkConfig);
30
31impl LibraryBenchmarkConfig {
32 /// Create a new `LibraryBenchmarkConfig` with initial callgrind arguments
33 ///
34 /// See also [`LibraryBenchmarkConfig::callgrind_args`].
35 ///
36 /// # Examples
37 ///
38 /// ```rust
39 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
40 /// # #[library_benchmark]
41 /// # fn some_func() {}
42 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
43 /// # fn main() {
44 /// use iai_callgrind::{LibraryBenchmarkConfig, main};
45 ///
46 /// main!(
47 /// config =
48 /// LibraryBenchmarkConfig::with_callgrind_args(["toggle-collect=something"]);
49 /// library_benchmark_groups = some_group
50 /// );
51 /// # }
52 /// ```
53 #[deprecated = "Please use with_callgrind_args"]
54 pub fn with_raw_callgrind_args<I, T>(args: T) -> Self
55 where
56 I: AsRef<str>,
57 T: IntoIterator<Item = I>,
58 {
59 Self(internal::InternalLibraryBenchmarkConfig {
60 env_clear: Option::default(),
61 callgrind_args: internal::InternalRawArgs::from_iter(args),
62 valgrind_args: internal::InternalRawArgs::default(),
63 envs: Vec::default(),
64 flamegraph_config: Option::default(),
65 regression_config: Option::default(),
66 tools: internal::InternalTools::default(),
67 tools_override: Option::default(),
68 output_format: Option::default(),
69 entry_point: Option::default(),
70 })
71 }
72
73 /// Add callgrind arguments to this `LibraryBenchmarkConfig`
74 ///
75 /// The arguments don't need to start with a flag: `--toggle-collect=some` or
76 /// `toggle-collect=some` are both understood.
77 ///
78 /// Not all callgrind arguments are understood by `iai-callgrind` or cause problems in
79 /// `iai-callgrind` if they would be applied. `iai-callgrind` will issue a warning in such
80 /// cases. Most of the defaults can be overwritten. The default settings are:
81 ///
82 /// * `--I1=32768,8,64`
83 /// * `--D1=32768,8,64`
84 /// * `--LL=8388608,16,64`
85 /// * `--cache-sim=yes`
86 /// * `--toggle-collect=...` (see also [`LibraryBenchmarkConfig::entry_point`])
87 /// * `--collect-atstart=no`
88 /// * `--compress-pos=no`
89 /// * `--compress-strings=no`
90 ///
91 /// Note that `toggle-collect` is an array and the default [`EntryPoint`] for library benchmarks
92 /// is the benchmark function.
93 ///
94 /// See also [Callgrind Command-line
95 /// Options](https://valgrind.org/docs/manual/cl-manual.html#cl-manual.options)
96 ///
97 /// # Examples
98 ///
99 /// ```rust
100 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
101 /// # #[library_benchmark]
102 /// # fn some_func() {}
103 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
104 /// # fn main() {
105 /// use iai_callgrind::{LibraryBenchmarkConfig, main};
106 ///
107 /// main!(
108 /// config = LibraryBenchmarkConfig::default()
109 /// .callgrind_args(["toggle-collect=something"]);
110 /// library_benchmark_groups = some_group
111 /// );
112 /// # }
113 /// ```
114 #[deprecated = "Please use callgrind_args"]
115 pub fn raw_callgrind_args<I, T>(&mut self, args: T) -> &mut Self
116 where
117 I: AsRef<str>,
118 T: IntoIterator<Item = I>,
119 {
120 #[allow(deprecated)]
121 self.raw_callgrind_args_iter(args);
122 self
123 }
124
125 /// Add elements of an iterator over callgrind arguments to this `LibraryBenchmarkConfig`
126 ///
127 /// See also [`LibraryBenchmarkConfig::callgrind_args`]
128 ///
129 /// # Examples
130 ///
131 /// ```rust
132 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
133 /// # #[library_benchmark]
134 /// # fn some_func() {}
135 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
136 /// use iai_callgrind::{LibraryBenchmarkConfig, main};
137 ///
138 /// # fn main() {
139 /// main!(
140 /// config = LibraryBenchmarkConfig::default()
141 /// .raw_callgrind_args_iter(["toggle-collect=something"].iter());
142 /// library_benchmark_groups = some_group
143 /// );
144 /// # }
145 /// ```
146 #[deprecated = "Please use callgrind_args"]
147 pub fn raw_callgrind_args_iter<I, T>(&mut self, args: T) -> &mut Self
148 where
149 I: AsRef<str>,
150 T: IntoIterator<Item = I>,
151 {
152 self.0.callgrind_args.extend_ignore_flag(args);
153 self
154 }
155
156 /// Create a new `LibraryBenchmarkConfig` with callgrind arguments
157 ///
158 /// See also [`LibraryBenchmarkConfig::callgrind_args`].
159 ///
160 /// # Examples
161 ///
162 /// ```rust
163 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
164 /// # #[library_benchmark]
165 /// # fn some_func() {}
166 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
167 /// # fn main() {
168 /// use iai_callgrind::{LibraryBenchmarkConfig, main};
169 ///
170 /// main!(
171 /// config =
172 /// LibraryBenchmarkConfig::with_callgrind_args(["toggle-collect=something"]);
173 /// library_benchmark_groups = some_group
174 /// );
175 /// # }
176 /// ```
177 pub fn with_callgrind_args<I, T>(args: T) -> Self
178 where
179 I: AsRef<str>,
180 T: IntoIterator<Item = I>,
181 {
182 Self(internal::InternalLibraryBenchmarkConfig {
183 callgrind_args: internal::InternalRawArgs::from_iter(args),
184 ..Default::default()
185 })
186 }
187
188 /// Add callgrind arguments to this `LibraryBenchmarkConfig`
189 ///
190 /// The arguments don't need to start with a flag: `--toggle-collect=some` or
191 /// `toggle-collect=some` are both understood.
192 ///
193 /// Not all callgrind arguments are understood by `iai-callgrind` or cause problems in
194 /// `iai-callgrind` if they would be applied. `iai-callgrind` will issue a warning in such
195 /// cases. Most of the defaults can be overwritten. The default settings are:
196 ///
197 /// * `--I1=32768,8,64`
198 /// * `--D1=32768,8,64`
199 /// * `--LL=8388608,16,64`
200 /// * `--cache-sim=yes`
201 /// * `--toggle-collect=...` (see also [`LibraryBenchmarkConfig::entry_point`])
202 /// * `--collect-atstart=no`
203 /// * `--compress-pos=no`
204 /// * `--compress-strings=no`
205 ///
206 /// Note that `toggle-collect` is an array and the default [`EntryPoint`] for library benchmarks
207 /// is the benchmark function.
208 ///
209 /// See also [Callgrind Command-line
210 /// Options](https://valgrind.org/docs/manual/cl-manual.html#cl-manual.options)
211 ///
212 /// # Examples
213 ///
214 /// ```rust
215 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
216 /// # #[library_benchmark]
217 /// # fn some_func() {}
218 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
219 /// # fn main() {
220 /// use iai_callgrind::{LibraryBenchmarkConfig, main};
221 ///
222 /// main!(
223 /// config = LibraryBenchmarkConfig::default()
224 /// .callgrind_args(["toggle-collect=something"]);
225 /// library_benchmark_groups = some_group
226 /// );
227 /// # }
228 /// ```
229 pub fn callgrind_args<I, T>(&mut self, args: T) -> &mut Self
230 where
231 I: AsRef<str>,
232 T: IntoIterator<Item = I>,
233 {
234 self.0.callgrind_args.extend_ignore_flag(args);
235 self
236 }
237
238 /// Pass valgrind arguments to all tools
239 ///
240 /// Only core [valgrind
241 /// arguments](https://valgrind.org/docs/manual/manual-core.html#manual-core.options) are
242 /// allowed.
243 ///
244 /// These arguments can be overwritten by tool specific arguments for example with
245 /// [`LibraryBenchmarkConfig::callgrind_args`] or [`crate::Tool::args`].
246 ///
247 /// # Examples
248 ///
249 /// Specify `--trace-children=no` for all configured tools (including callgrind):
250 ///
251 /// ```rust
252 /// # use iai_callgrind::{library_benchmark_group, library_benchmark};
253 /// # #[library_benchmark] fn bench_me() {}
254 /// # library_benchmark_group!(
255 /// # name = my_group;
256 /// # benchmarks = bench_me
257 /// # );
258 /// use iai_callgrind::{main, LibraryBenchmarkConfig, Tool, ValgrindTool};
259 ///
260 /// # fn main() {
261 /// main!(
262 /// config = LibraryBenchmarkConfig::default()
263 /// .valgrind_args(["--trace-children=no"])
264 /// .tool(Tool::new(ValgrindTool::DHAT));
265 /// library_benchmark_groups = my_group
266 /// );
267 /// # }
268 /// ```
269 ///
270 /// Overwrite the valgrind argument `--num-callers=25` for `DHAT` with `--num-callers=30`:
271 ///
272 /// ```rust
273 /// # use iai_callgrind::{library_benchmark_group, library_benchmark};
274 /// # #[library_benchmark] fn bench_me() {}
275 /// # library_benchmark_group!(
276 /// # name = my_group;
277 /// # benchmarks = bench_me
278 /// # );
279 /// use iai_callgrind::{main, LibraryBenchmarkConfig, Tool, ValgrindTool};
280 ///
281 /// # fn main() {
282 /// main!(
283 /// config = LibraryBenchmarkConfig::default()
284 /// .valgrind_args(["--num-callers=25"])
285 /// .tool(Tool::new(ValgrindTool::DHAT)
286 /// .args(["--num-callers=30"])
287 /// );
288 /// library_benchmark_groups = my_group
289 /// );
290 /// # }
291 /// ```
292 pub fn valgrind_args<I, T>(&mut self, args: T) -> &mut Self
293 where
294 I: AsRef<str>,
295 T: IntoIterator<Item = I>,
296 {
297 self.0.valgrind_args.extend_ignore_flag(args);
298 self
299 }
300
301 /// Clear the environment variables before running a benchmark (Default: true)
302 ///
303 /// # Examples
304 ///
305 /// ```rust
306 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
307 /// # #[library_benchmark]
308 /// # fn some_func() {}
309 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
310 /// use iai_callgrind::{LibraryBenchmarkConfig, main};
311 ///
312 /// # fn main() {
313 /// main!(
314 /// config = LibraryBenchmarkConfig::default().env_clear(false);
315 /// library_benchmark_groups = some_group
316 /// );
317 /// # }
318 /// ```
319 pub fn env_clear(&mut self, value: bool) -> &mut Self {
320 self.0.env_clear = Some(value);
321 self
322 }
323
324 /// Add an environment variables which will be available in library benchmarks
325 ///
326 /// These environment variables are available independently of the setting of
327 /// [`LibraryBenchmarkConfig::env_clear`].
328 ///
329 /// # Examples
330 ///
331 /// An example for a custom environment variable, available in all benchmarks:
332 ///
333 /// ```rust
334 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
335 /// # #[library_benchmark]
336 /// # fn some_func() {}
337 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
338 /// use iai_callgrind::{LibraryBenchmarkConfig, main};
339 ///
340 /// # fn main() {
341 /// main!(
342 /// config = LibraryBenchmarkConfig::default().env("FOO", "BAR");
343 /// library_benchmark_groups = some_group
344 /// );
345 /// # }
346 /// ```
347 pub fn env<K, V>(&mut self, key: K, value: V) -> &mut Self
348 where
349 K: Into<OsString>,
350 V: Into<OsString>,
351 {
352 self.0.envs.push((key.into(), Some(value.into())));
353 self
354 }
355
356 /// Add multiple environment variables which will be available in library benchmarks
357 ///
358 /// See also [`LibraryBenchmarkConfig::env`] for more details.
359 ///
360 /// # Examples
361 ///
362 /// ```rust
363 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
364 /// # #[library_benchmark]
365 /// # fn some_func() {}
366 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
367 /// use iai_callgrind::{LibraryBenchmarkConfig, main};
368 ///
369 /// # fn main() {
370 /// main!(
371 /// config =
372 /// LibraryBenchmarkConfig::default().envs([("MY_CUSTOM_VAR", "SOME_VALUE"), ("FOO", "BAR")]);
373 /// library_benchmark_groups = some_group
374 /// );
375 /// # }
376 /// ```
377 pub fn envs<K, V, T>(&mut self, envs: T) -> &mut Self
378 where
379 K: Into<OsString>,
380 V: Into<OsString>,
381 T: IntoIterator<Item = (K, V)>,
382 {
383 self.0
384 .envs
385 .extend(envs.into_iter().map(|(k, v)| (k.into(), Some(v.into()))));
386 self
387 }
388
389 /// Specify a pass-through environment variable
390 ///
391 /// Usually, the environment variables before running a library benchmark are cleared
392 /// but specifying pass-through variables makes this environment variable available to
393 /// the benchmark as it actually appeared in the root environment.
394 ///
395 /// Pass-through environment variables are ignored if they don't exist in the root
396 /// environment.
397 ///
398 /// # Examples
399 ///
400 /// Here, we chose to pass through the original value of the `HOME` variable:
401 ///
402 /// ```rust
403 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
404 /// # #[library_benchmark]
405 /// # fn some_func() {}
406 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
407 /// use iai_callgrind::{LibraryBenchmarkConfig, main};
408 ///
409 /// # fn main() {
410 /// main!(
411 /// config = LibraryBenchmarkConfig::default().pass_through_env("HOME");
412 /// library_benchmark_groups = some_group
413 /// );
414 /// # }
415 /// ```
416 pub fn pass_through_env<K>(&mut self, key: K) -> &mut Self
417 where
418 K: Into<OsString>,
419 {
420 self.0.envs.push((key.into(), None));
421 self
422 }
423
424 /// Specify multiple pass-through environment variables
425 ///
426 /// See also [`LibraryBenchmarkConfig::pass_through_env`].
427 ///
428 /// # Examples
429 ///
430 /// ```rust
431 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
432 /// # #[library_benchmark]
433 /// # fn some_func() {}
434 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
435 /// use iai_callgrind::{LibraryBenchmarkConfig, main};
436 ///
437 /// # fn main() {
438 /// main!(
439 /// config = LibraryBenchmarkConfig::default().pass_through_envs(["HOME", "USER"]);
440 /// library_benchmark_groups = some_group
441 /// );
442 /// # }
443 /// ```
444 pub fn pass_through_envs<K, T>(&mut self, envs: T) -> &mut Self
445 where
446 K: Into<OsString>,
447 T: IntoIterator<Item = K>,
448 {
449 self.0
450 .envs
451 .extend(envs.into_iter().map(|k| (k.into(), None)));
452 self
453 }
454
455 /// Option to produce flamegraphs from callgrind output using the [`crate::FlamegraphConfig`]
456 ///
457 /// # Examples
458 ///
459 /// ```rust
460 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
461 /// # #[library_benchmark]
462 /// # fn some_func() {}
463 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
464 /// use iai_callgrind::{LibraryBenchmarkConfig, main, FlamegraphConfig};
465 ///
466 /// # fn main() {
467 /// main!(
468 /// config = LibraryBenchmarkConfig::default().flamegraph(FlamegraphConfig::default());
469 /// library_benchmark_groups = some_group
470 /// );
471 /// # }
472 /// ```
473 pub fn flamegraph<T>(&mut self, config: T) -> &mut Self
474 where
475 T: Into<internal::InternalFlamegraphConfig>,
476 {
477 self.0.flamegraph_config = Some(config.into());
478 self
479 }
480
481 /// Enable performance regression checks with a [`crate::RegressionConfig`]
482 ///
483 /// # Examples
484 ///
485 /// ```rust
486 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
487 /// # #[library_benchmark]
488 /// # fn some_func() {}
489 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
490 /// use iai_callgrind::{LibraryBenchmarkConfig, main, RegressionConfig};
491 ///
492 /// # fn main() {
493 /// main!(
494 /// config = LibraryBenchmarkConfig::default().regression(RegressionConfig::default());
495 /// library_benchmark_groups = some_group
496 /// );
497 /// # }
498 /// ```
499 pub fn regression<T>(&mut self, config: T) -> &mut Self
500 where
501 T: Into<internal::InternalRegressionConfig>,
502 {
503 self.0.regression_config = Some(config.into());
504 self
505 }
506
507 /// Add a configuration to run a valgrind [`crate::Tool`] in addition to callgrind
508 ///
509 /// # Examples
510 ///
511 /// ```rust
512 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
513 /// # #[library_benchmark]
514 /// # fn some_func() {}
515 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
516 /// use iai_callgrind::{LibraryBenchmarkConfig, main, Tool, ValgrindTool};
517 ///
518 /// # fn main() {
519 /// main!(
520 /// config = LibraryBenchmarkConfig::default()
521 /// .tool(Tool::new(ValgrindTool::DHAT));
522 /// library_benchmark_groups = some_group
523 /// );
524 /// # }
525 /// ```
526 pub fn tool<T>(&mut self, tool: T) -> &mut Self
527 where
528 T: Into<internal::InternalTool>,
529 {
530 self.0.tools.update(tool.into());
531 self
532 }
533
534 /// Add multiple configurations to run valgrind [`crate::Tool`]s in addition to callgrind
535 ///
536 /// # Examples
537 ///
538 /// ```rust
539 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
540 /// # #[library_benchmark]
541 /// # fn some_func() {}
542 /// # library_benchmark_group!(name = some_group; benchmarks = some_func);
543 /// use iai_callgrind::{LibraryBenchmarkConfig, main, Tool, ValgrindTool};
544 ///
545 /// # fn main() {
546 /// main!(
547 /// config = LibraryBenchmarkConfig::default()
548 /// .tools(
549 /// [
550 /// Tool::new(ValgrindTool::DHAT),
551 /// Tool::new(ValgrindTool::Massif)
552 /// ]
553 /// );
554 /// library_benchmark_groups = some_group
555 /// );
556 /// # }
557 /// ```
558 pub fn tools<I, T>(&mut self, tools: T) -> &mut Self
559 where
560 I: Into<internal::InternalTool>,
561 T: IntoIterator<Item = I>,
562 {
563 self.0.tools.update_all(tools.into_iter().map(Into::into));
564 self
565 }
566
567 /// Override previously defined configurations of valgrind [`crate::Tool`]s
568 ///
569 /// Usually, if specifying [`crate::Tool`] configurations with [`LibraryBenchmarkConfig::tool`]
570 /// these tools are appended to the configuration of a [`LibraryBenchmarkConfig`] of
571 /// higher-levels. Specifying a [`crate::Tool`] with this method overrides previously defined
572 /// configurations.
573 ///
574 /// Note that [`crate::Tool`]s specified with [`LibraryBenchmarkConfig::tool`] will be ignored,
575 /// if in the very same `LibraryBenchmarkConfig`, [`crate::Tool`]s are specified by this method
576 /// (or [`LibraryBenchmarkConfig::tools_override`]).
577 ///
578 /// # Examples
579 ///
580 /// The following will run `DHAT` and `Massif` (and the default callgrind) for all benchmarks in
581 /// `main!` besides for `some_func` which will just run `Memcheck` (and callgrind).
582 ///
583 /// ```rust
584 /// use iai_callgrind::{
585 /// main, library_benchmark, library_benchmark_group, LibraryBenchmarkConfig, Tool, ValgrindTool
586 /// };
587 ///
588 /// #[library_benchmark(config = LibraryBenchmarkConfig::default()
589 /// .tool_override(
590 /// Tool::new(ValgrindTool::Memcheck)
591 /// )
592 /// )]
593 /// fn some_func() {}
594 ///
595 /// library_benchmark_group!(
596 /// name = some_group;
597 /// benchmarks = some_func
598 /// );
599 ///
600 /// # fn main() {
601 /// main!(
602 /// config = LibraryBenchmarkConfig::default()
603 /// .tools(
604 /// [
605 /// Tool::new(ValgrindTool::DHAT),
606 /// Tool::new(ValgrindTool::Massif)
607 /// ]
608 /// );
609 /// library_benchmark_groups = some_group
610 /// );
611 /// # }
612 /// ```
613 pub fn tool_override<T>(&mut self, tool: T) -> &mut Self
614 where
615 T: Into<internal::InternalTool>,
616 {
617 self.0
618 .tools_override
619 .get_or_insert(internal::InternalTools::default())
620 .update(tool.into());
621 self
622 }
623
624 /// Override previously defined configurations of valgrind [`crate::Tool`]s
625 ///
626 /// See also [`LibraryBenchmarkConfig::tool_override`].
627 ///
628 /// # Examples
629 ///
630 /// The following will run `DHAT` (and the default callgrind) for all benchmarks in
631 /// `main!` besides for `some_func` which will run `Massif` and `Memcheck` (and callgrind).
632 ///
633 /// ```rust
634 /// use iai_callgrind::{
635 /// main, library_benchmark, library_benchmark_group, LibraryBenchmarkConfig, Tool, ValgrindTool
636 /// };
637 ///
638 /// #[library_benchmark(config = LibraryBenchmarkConfig::default()
639 /// .tools_override([
640 /// Tool::new(ValgrindTool::Massif),
641 /// Tool::new(ValgrindTool::Memcheck)
642 /// ])
643 /// )]
644 /// fn some_func() {}
645 ///
646 /// library_benchmark_group!(
647 /// name = some_group;
648 /// benchmarks = some_func
649 /// );
650 ///
651 /// # fn main() {
652 /// main!(
653 /// config = LibraryBenchmarkConfig::default()
654 /// .tool(
655 /// Tool::new(ValgrindTool::DHAT),
656 /// );
657 /// library_benchmark_groups = some_group
658 /// );
659 /// # }
660 /// ```
661 pub fn tools_override<I, T>(&mut self, tools: T) -> &mut Self
662 where
663 I: Into<internal::InternalTool>,
664 T: IntoIterator<Item = I>,
665 {
666 self.0
667 .tools_override
668 .get_or_insert(internal::InternalTools::default())
669 .update_all(tools.into_iter().map(Into::into));
670 self
671 }
672
673 /// Set or unset the entry point for a benchmark
674 ///
675 /// Iai-Callgrind sets the [`--toggle-collect`] argument of callgrind to the benchmark function
676 /// which we call [`EntryPoint::Default`]. Specifying a `--toggle-collect` argument, sets
677 /// automatically `--collect-at-start=no`. This ensures that only the metrics from the benchmark
678 /// itself are collected and not the `setup` or `teardown` or anything before/after the
679 /// benchmark function.
680 ///
681 ///
682 /// However, there are cases when the default toggle is not enough [`EntryPoint::Custom`] or in
683 /// the way [`EntryPoint::None`].
684 ///
685 /// Setting [`EntryPoint::Custom`] is convenience for disabling the entry point with
686 /// [`EntryPoint::None`] and setting `--toggle-collect=CUSTOM_ENTRY_POINT` in
687 /// [`LibraryBenchmarkConfig::callgrind_args`]. [`EntryPoint::Custom`] can be useful if you
688 /// want to benchmark a private function and only need the function in the benchmark function as
689 /// access point. [`EntryPoint::Custom`] accepts glob patterns the same way as
690 /// [`--toggle-collect`] does.
691 ///
692 /// # Examples
693 ///
694 /// If you're using callgrind client requests either in the benchmark function itself or in your
695 /// library, then using [`EntryPoint::None`] is presumably be required. Consider the following
696 /// example (`DEFAULT_ENTRY_POINT` marks the default entry point):
697 #[cfg_attr(not(feature = "client_requests_defs"), doc = "```rust,ignore")]
698 #[cfg_attr(feature = "client_requests_defs", doc = "```rust")]
699 /// use iai_callgrind::{
700 /// main, LibraryBenchmarkConfig,library_benchmark, library_benchmark_group
701 /// };
702 /// use std::hint::black_box;
703 ///
704 /// fn to_be_benchmarked() -> u64 {
705 /// println!("Some info output");
706 /// iai_callgrind::client_requests::callgrind::start_instrumentation();
707 /// let result = {
708 /// // some heavy calculations
709 /// # 10
710 /// };
711 /// iai_callgrind::client_requests::callgrind::stop_instrumentation();
712 ///
713 /// result
714 /// }
715 ///
716 /// #[library_benchmark]
717 /// fn some_bench() -> u64 { // <-- DEFAULT ENTRY POINT
718 /// black_box(to_be_benchmarked())
719 /// }
720 ///
721 /// library_benchmark_group!(name = some_group; benchmarks = some_bench);
722 /// # fn main() {
723 /// main!(library_benchmark_groups = some_group);
724 /// # }
725 /// ```
726 /// In the example above [`EntryPoint::Default`] is active, so the counting of events starts
727 /// when the `some_bench` function is entered. In `to_be_benchmarked`, the client request
728 /// `start_instrumentation` does effectively nothing and `stop_instrumentation` will stop the
729 /// event counting as requested. This is most likely not what you intended. The event counting
730 /// should start with `start_instrumentation`. To achieve this, you can set [`EntryPoint::None`]
731 /// which removes the default toggle, but also `--collect-at-start=no`. So, you need to specify
732 /// `--collect-at-start=no` in [`LibraryBenchmarkConfig::callgrind_args`]. The example would
733 /// then look like this:
734 /// ```rust
735 /// use std::hint::black_box;
736 ///
737 /// use iai_callgrind::{library_benchmark, EntryPoint, LibraryBenchmarkConfig};
738 /// # use iai_callgrind::{library_benchmark_group, main};
739 /// # fn to_be_benchmarked() -> u64 { 10 }
740 ///
741 /// // ...
742 ///
743 /// #[library_benchmark(
744 /// config = LibraryBenchmarkConfig::default()
745 /// .callgrind_args(["--collect-at-start=no"])
746 /// .entry_point(EntryPoint::None)
747 /// )]
748 /// fn some_bench() -> u64 {
749 /// black_box(to_be_benchmarked())
750 /// }
751 ///
752 /// // ...
753 ///
754 /// # library_benchmark_group!(name = some_group; benchmarks = some_bench);
755 /// # fn main() {
756 /// # main!(library_benchmark_groups = some_group);
757 /// # }
758 /// ```
759 /// [`--toggle-collect`]: https://valgrind.org/docs/manual/cl-manual.html#cl-manual.options
760 pub fn entry_point<T>(&mut self, entry_point: T) -> &mut Self
761 where
762 T: Into<EntryPoint>,
763 {
764 self.0.entry_point = Some(entry_point.into());
765 self
766 }
767
768 /// Configure the [`crate::OutputFormat`] of the terminal output of Iai-Callgrind
769 ///
770 /// # Examples
771 ///
772 /// ```rust
773 /// use iai_callgrind::{main, LibraryBenchmarkConfig, OutputFormat};
774 /// # use iai_callgrind::{library_benchmark, library_benchmark_group};
775 /// # #[library_benchmark]
776 /// # fn some_func() {}
777 /// # library_benchmark_group!(
778 /// # name = some_group;
779 /// # benchmarks = some_func
780 /// # );
781 /// # fn main() {
782 /// main!(
783 /// config = LibraryBenchmarkConfig::default()
784 /// .output_format(OutputFormat::default()
785 /// .truncate_description(Some(200))
786 /// );
787 /// library_benchmark_groups = some_group
788 /// );
789 /// # }
790 pub fn output_format<T>(&mut self, output_format: T) -> &mut Self
791 where
792 T: Into<internal::InternalOutputFormat>,
793 {
794 self.0.output_format = Some(output_format.into());
795 self
796 }
797}