]> git.lizzy.rs Git - rust.git/commitdiff
Generate self-profiler types with macros
authorWesley Wiser <wwiser@gmail.com>
Tue, 24 Jul 2018 01:52:39 +0000 (21:52 -0400)
committerWesley Wiser <wwiser@gmail.com>
Thu, 2 Aug 2018 22:57:24 +0000 (18:57 -0400)
src/librustc/util/profiling.rs

index ee00673dccdcba2141f8e486951a86f046a77538..447b75e547f01d903c6fec73fe38aac2933fbb49 100644 (file)
 use std::io::{self, StdoutLock, Write};
 use std::time::Instant;
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
-pub enum ProfileCategory {
-    Parsing,
-    Expansion,
-    TypeChecking,
-    BorrowChecking,
-    Codegen,
-    Linking,
-    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(),
+macro_rules! define_categories {
+    ($($name:ident,)*) => {
+        #[derive(Clone, Copy, Debug, PartialEq, Eq)]
+        pub enum ProfileCategory {
+            $($name),*
         }
-    }
-}
 
-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,
+        #[allow(bad_style)]
+        struct Categories<T> {
+            $($name: T),*
         }
-    }
 
-    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,
+        impl<T: Default> Categories<T> {
+            fn new() -> Categories<T> {
+                Categories {
+                    $($name: T::default()),*
+                }
+            }
         }
-    }
-}
 
-struct CategoryData {
-    times: Categories<u64>,
-    query_counts: Categories<(u64, u64)>,
-}
+        impl<T> Categories<T> {
+            fn get(&self, category: ProfileCategory) -> &T {
+                match category {
+                    $(ProfileCategory::$name => &self.$name),*
+                }
+            }
 
-impl CategoryData {
-    fn new() -> CategoryData {
-        CategoryData {
-            times: Categories::new(),
-            query_counts: Categories::new(),
+            fn set(&mut self, category: ProfileCategory, value: T) {
+                match category {
+                    $(ProfileCategory::$name => self.$name = value),*
+                }
+            }
         }
-    }
 
-    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();
-            };
+        struct CategoryData {
+            times: Categories<u64>,
+            query_counts: Categories<(u64, u64)>,
         }
 
-        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);
-    }
+        impl CategoryData {
+            fn new() -> CategoryData {
+                CategoryData {
+                    times: Categories::new(),
+                    query_counts: Categories::new(),
+                }
+            }
 
-    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))
-                )
-            }}
-        }
+            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();
+                )*
+            }
 
-        format!("[
-            {},
-            {},
-            {},
-            {},
-            {},
-            {},
-            {}
-        ]",
-            j!("Parsing", parsing),
-            j!("Expansion", expansion),
-            j!("TypeChecking", type_checking),
-            j!("BorrowChecking", borrow_checking),
-            j!("Codegen", codegen),
-            j!("Linking", linking),
-            j!("Other", other)
-        )
+            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,
+    Expansion,
+    TypeChecking,
+    BorrowChecking,
+    Codegen,
+    Linking,
+    Other,
+}
+
 pub struct SelfProfiler {
     timer_stack: Vec<ProfileCategory>,
     data: CategoryData,