fae/profiler.rs
1//! Module for reading the profiling data that `fae` collects. If the
2//! `profiler` feature is disabled, all the functions are no-ops, and
3//! there will be no profiling overhead. Probably not very useful
4//! outside of this crate's development.
5//!
6//! If using this, remember to call
7//! [`profiler::refresh()`](fn.refresh.html) at the start of each
8//! frame!
9
10/// The data collected by `fae` internals. Returned by
11/// [`profiler::read`](fn.read.html).
12#[derive(Clone, Debug)]
13pub struct ProfilingData {
14 /// The amount of glyphs that had to be rasterized during this
15 /// frame (ie. they weren't in the glyph cache, and drawing the
16 /// glyph was slow, as it had to be rasterized).
17 pub glyph_cache_misses: u32,
18 /// The amount of glyphs that didn't have to rasterized during
19 /// this frame (ie. they were in the glyph cache, and drawing the
20 /// glyph was very fast).
21 pub glyph_cache_hits: u32,
22 /// The amount of glyphs that were rendered during this frame.
23 pub glyphs_drawn: u32,
24 /// The amount of quads that were rendered during this frame
25 /// (includes the glyphs, each one is a quad).
26 pub quads_drawn: u32,
27 /// The amount of times a glyph had to be rasterized in the
28 /// application so far.
29 pub glyphs_rasterized: u32,
30}
31
32impl ProfilingData {
33 const fn cleared() -> ProfilingData {
34 ProfilingData {
35 glyph_cache_misses: 0,
36 glyph_cache_hits: 0,
37 glyphs_drawn: 0,
38 quads_drawn: 0,
39 glyphs_rasterized: 0,
40 }
41 }
42}
43
44#[cfg(feature = "profiler")]
45pub use actual::*;
46#[cfg(not(feature = "profiler"))]
47pub use dummy::*;
48
49#[cfg(not(feature = "profiler"))]
50mod dummy {
51 use super::ProfilingData;
52
53 static CLEARED_DATA: ProfilingData = ProfilingData::cleared();
54
55 /// Resets frame-specific counters.
56 pub fn refresh() {}
57 pub(crate) fn write<F: FnOnce(&mut ProfilingData) + Copy>(_f: F) {}
58
59 /// Returns a copy of the last frame's profiling data. If the
60 /// `profiler` feature is disabled, it will always be zeroed.
61 pub fn read() -> ProfilingData {
62 CLEARED_DATA.clone()
63 }
64}
65
66#[cfg(feature = "profiler")]
67mod actual {
68 use super::ProfilingData;
69 use std::sync::Mutex;
70
71 impl ProfilingData {
72 fn copy_from(&mut self, other: &ProfilingData) {
73 *self = other.clone();
74 }
75
76 fn clear(&mut self) {
77 *self = ProfilingData::cleared();
78 }
79 }
80
81 lazy_static::lazy_static! {
82 static ref FRONT: Mutex<ProfilingData> = Mutex::new(ProfilingData::cleared());
83 static ref BACK: Mutex<ProfilingData> = Mutex::new(ProfilingData::cleared());
84 }
85
86 /// Resets frame-specific counters.
87 pub fn refresh() {
88 if let (Ok(ref mut front), Ok(ref mut back)) = (FRONT.lock(), BACK.lock()) {
89 let temp = back.glyphs_rasterized;
90 front.copy_from(back);
91 back.clear();
92 back.glyphs_rasterized = temp;
93 }
94 }
95
96 pub(crate) fn write<F: FnOnce(&mut ProfilingData) + Copy>(f: F) {
97 if let Ok(ref mut instance) = BACK.lock() {
98 f(instance);
99 }
100 }
101
102 /// Returns a copy of the last frame's profiling data. If the
103 /// `profiler` feature is disabled, it will always be zeroed and
104 /// initialized on the spot.
105 pub fn read() -> ProfilingData {
106 if let Ok(instance) = FRONT.lock() {
107 instance.clone()
108 } else {
109 ProfilingData::cleared()
110 }
111 }
112}