Generate self-profiler types with macros
This commit is contained in:
parent
60c2e9a329
commit
2d3a0a9927
@ -14,8 +14,104 @@ use std::fs;
|
|||||||
use std::io::{self, StdoutLock, Write};
|
use std::io::{self, StdoutLock, Write};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
macro_rules! define_categories {
|
||||||
pub enum ProfileCategory {
|
($($name:ident,)*) => {
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub enum ProfileCategory {
|
||||||
|
$($name),*
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(bad_style)]
|
||||||
|
struct Categories<T> {
|
||||||
|
$($name: T),*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Default> Categories<T> {
|
||||||
|
fn new() -> Categories<T> {
|
||||||
|
Categories {
|
||||||
|
$($name: T::default()),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Categories<T> {
|
||||||
|
fn get(&self, category: ProfileCategory) -> &T {
|
||||||
|
match category {
|
||||||
|
$(ProfileCategory::$name => &self.$name),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set(&mut self, category: ProfileCategory, value: T) {
|
||||||
|
match category {
|
||||||
|
$(ProfileCategory::$name => self.$name = value),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CategoryData {
|
||||||
|
times: Categories<u64>,
|
||||||
|
query_counts: Categories<(u64, u64)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CategoryData {
|
||||||
|
fn new() -> CategoryData {
|
||||||
|
CategoryData {
|
||||||
|
times: Categories::new(),
|
||||||
|
query_counts: Categories::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print(&self, lock: &mut StdoutLock) {
|
||||||
|
writeln!(lock, "| Phase | Time (ms) | Queries | Hits (%) |")
|
||||||
|
.unwrap();
|
||||||
|
writeln!(lock, "| ---------------- | -------------- | -------------- | -------- |")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
$(
|
||||||
|
let (hits, total) = self.query_counts.$name;
|
||||||
|
let (hits, total) = if total > 0 {
|
||||||
|
(format!("{:.2}",
|
||||||
|
(((hits as f32) / (total as f32)) * 100.0)), total.to_string())
|
||||||
|
} else {
|
||||||
|
("".into(), "".into())
|
||||||
|
};
|
||||||
|
|
||||||
|
writeln!(
|
||||||
|
lock,
|
||||||
|
"| {0: <16} | {1: <14} | {2: <14} | {3: <8} |",
|
||||||
|
stringify!($name),
|
||||||
|
self.times.$name / 1_000_000,
|
||||||
|
total,
|
||||||
|
hits
|
||||||
|
).unwrap();
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json(&self) -> String {
|
||||||
|
let mut json = String::from("[");
|
||||||
|
|
||||||
|
$(
|
||||||
|
let (hits, total) = self.query_counts.$name;
|
||||||
|
|
||||||
|
json.push_str(&format!(
|
||||||
|
"{{ \"category\": {}, \"time_ms\": {},
|
||||||
|
\"query_count\": {}, \"query_hits\": {} }}",
|
||||||
|
stringify!($name),
|
||||||
|
self.times.$name / 1_000_000,
|
||||||
|
total,
|
||||||
|
format!("{:.2}", (((hits as f32) / (total as f32)) * 100.0))
|
||||||
|
));
|
||||||
|
)*
|
||||||
|
|
||||||
|
json.push(']');
|
||||||
|
|
||||||
|
json
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_categories! {
|
||||||
Parsing,
|
Parsing,
|
||||||
Expansion,
|
Expansion,
|
||||||
TypeChecking,
|
TypeChecking,
|
||||||
@ -25,141 +121,6 @@ pub enum ProfileCategory {
|
|||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Categories<T> {
|
|
||||||
parsing: T,
|
|
||||||
expansion: T,
|
|
||||||
type_checking: T,
|
|
||||||
borrow_checking: T,
|
|
||||||
codegen: T,
|
|
||||||
linking: T,
|
|
||||||
other: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Default> Categories<T> {
|
|
||||||
fn new() -> Categories<T> {
|
|
||||||
Categories {
|
|
||||||
parsing: T::default(),
|
|
||||||
expansion: T::default(),
|
|
||||||
type_checking: T::default(),
|
|
||||||
borrow_checking: T::default(),
|
|
||||||
codegen: T::default(),
|
|
||||||
linking: T::default(),
|
|
||||||
other: T::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Categories<T> {
|
|
||||||
fn get(&self, category: ProfileCategory) -> &T {
|
|
||||||
match category {
|
|
||||||
ProfileCategory::Parsing => &self.parsing,
|
|
||||||
ProfileCategory::Expansion => &self.expansion,
|
|
||||||
ProfileCategory::TypeChecking => &self.type_checking,
|
|
||||||
ProfileCategory::BorrowChecking => &self.borrow_checking,
|
|
||||||
ProfileCategory::Codegen => &self.codegen,
|
|
||||||
ProfileCategory::Linking => &self.linking,
|
|
||||||
ProfileCategory::Other => &self.other,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set(&mut self, category: ProfileCategory, value: T) {
|
|
||||||
match category {
|
|
||||||
ProfileCategory::Parsing => self.parsing = value,
|
|
||||||
ProfileCategory::Expansion => self.expansion = value,
|
|
||||||
ProfileCategory::TypeChecking => self.type_checking = value,
|
|
||||||
ProfileCategory::BorrowChecking => self.borrow_checking = value,
|
|
||||||
ProfileCategory::Codegen => self.codegen = value,
|
|
||||||
ProfileCategory::Linking => self.linking = value,
|
|
||||||
ProfileCategory::Other => self.other = value,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CategoryData {
|
|
||||||
times: Categories<u64>,
|
|
||||||
query_counts: Categories<(u64, u64)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CategoryData {
|
|
||||||
fn new() -> CategoryData {
|
|
||||||
CategoryData {
|
|
||||||
times: Categories::new(),
|
|
||||||
query_counts: Categories::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print(&self, lock: &mut StdoutLock) {
|
|
||||||
macro_rules! p {
|
|
||||||
($name:tt, $rustic_name:ident) => {
|
|
||||||
let (hits, total) = self.query_counts.$rustic_name;
|
|
||||||
let (hits, total) = if total > 0 {
|
|
||||||
(format!("{:.2}",
|
|
||||||
(((hits as f32) / (total as f32)) * 100.0)), total.to_string())
|
|
||||||
} else {
|
|
||||||
("".into(), "".into())
|
|
||||||
};
|
|
||||||
|
|
||||||
writeln!(
|
|
||||||
lock,
|
|
||||||
"| {0: <16} | {1: <14} | {2: <14} | {3: <8} |",
|
|
||||||
$name,
|
|
||||||
self.times.$rustic_name / 1_000_000,
|
|
||||||
total,
|
|
||||||
hits
|
|
||||||
).unwrap();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
writeln!(lock, "| Phase | Time (ms) | Queries | Hits (%) |")
|
|
||||||
.unwrap();
|
|
||||||
writeln!(lock, "| ---------------- | -------------- | -------------- | -------- |")
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
p!("Parsing", parsing);
|
|
||||||
p!("Expansion", expansion);
|
|
||||||
p!("TypeChecking", type_checking);
|
|
||||||
p!("BorrowChecking", borrow_checking);
|
|
||||||
p!("Codegen", codegen);
|
|
||||||
p!("Linking", linking);
|
|
||||||
p!("Other", other);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn json(&self) -> String {
|
|
||||||
macro_rules! j {
|
|
||||||
($category:tt, $rustic_name:ident) => {{
|
|
||||||
let (hits, total) = self.query_counts.$rustic_name;
|
|
||||||
|
|
||||||
format!(
|
|
||||||
"{{ \"category\": {}, \"time_ms\": {},
|
|
||||||
\"query_count\": {}, \"query_hits\": {} }}",
|
|
||||||
stringify!($category),
|
|
||||||
self.times.$rustic_name / 1_000_000,
|
|
||||||
total,
|
|
||||||
format!("{:.2}", (((hits as f32) / (total as f32)) * 100.0))
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
format!("[
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{}
|
|
||||||
]",
|
|
||||||
j!("Parsing", parsing),
|
|
||||||
j!("Expansion", expansion),
|
|
||||||
j!("TypeChecking", type_checking),
|
|
||||||
j!("BorrowChecking", borrow_checking),
|
|
||||||
j!("Codegen", codegen),
|
|
||||||
j!("Linking", linking),
|
|
||||||
j!("Other", other)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SelfProfiler {
|
pub struct SelfProfiler {
|
||||||
timer_stack: Vec<ProfileCategory>,
|
timer_stack: Vec<ProfileCategory>,
|
||||||
data: CategoryData,
|
data: CategoryData,
|
||||||
|
Loading…
Reference in New Issue
Block a user