Skip to main content

max / quasi

2.1 KB · 51 lines History Blame Raw
1 //! Allocation counting, compiled in only under `--features count`.
2 //!
3 //! The count is the number that matters. It is stable across machines and
4 //! across load, which a wall-clock number on a shared dev box is not, and it is
5 //! what an emitter change actually moves. The timing run answers "is this
6 //! faster here today"; this one answers "does this do less work".
7 //!
8 //! # Why `dhat` rather than a hand-written `GlobalAlloc`
9 //!
10 //! The workspace sets `unsafe_code = "forbid"`, and a `GlobalAlloc`
11 //! implementation cannot be written without `unsafe`. `forbid` is not
12 //! overridable by an `#[allow]`, so a hand-rolled counter would mean this crate
13 //! opting out of the workspace lint block, and that block is meant to be
14 //! identical everywhere. A dependency that is off by default is the cheaper
15 //! trade: `dhat` holds the `unsafe`, and the bench holds none.
16 //!
17 //! It also answers the reason the two measurements are two builds. `dhat`'s
18 //! allocator is real instrumentation and a timing number taken through it would
19 //! be a number about the instrumentation, so `count` is never on in a timing
20 //! run.
21
22 /// The counting allocator, in place only in a `--features count` build.
23 #[global_allocator]
24 static ALLOC: dhat::Alloc = dhat::Alloc;
25
26 /// A running profiler, held for as long as measurements are being taken.
27 pub struct Session(dhat::Profiler);
28
29 impl Session {
30 /// Start counting.
31 ///
32 /// `testing()` keeps `dhat` from writing its JSON output file: the bench
33 /// wants two integers, not a profile to open in a viewer.
34 #[must_use]
35 pub fn start() -> Self {
36 Self(dhat::Profiler::builder().testing().build())
37 }
38 }
39
40 /// Allocations and bytes so far in this session.
41 ///
42 /// `total_blocks` is every allocation since the profiler started, which is what
43 /// "how many allocations does rendering this screen take" means. The live and
44 /// peak figures `dhat` also carries are about retention, and a renderer that
45 /// returns a `String` and drops everything else has nothing interesting there.
46 #[must_use]
47 pub fn read() -> (u64, u64) {
48 let stats = dhat::HeapStats::get();
49 (stats.total_blocks, stats.total_bytes)
50 }
51