]> git.lizzy.rs Git - rust.git/commitdiff
profiling with -Z profile-queries recognizes -Z time-passes
authorMatthew Hammer <matthew.hammer@colorado.edu>
Fri, 21 Jul 2017 18:32:38 +0000 (12:32 -0600)
committerMatthew Hammer <matthew.hammer@colorado.edu>
Wed, 23 Aug 2017 15:26:48 +0000 (09:26 -0600)
src/librustc/util/common.rs
src/librustc_driver/profile/mod.rs
src/librustc_driver/profile/trace.rs

index 2e4aaeee2356e9a36b54fae8a0a6ca9f3d2193c8..bce2a66a308a5501875f64398033c6edefb23b2a 100644 (file)
@@ -51,8 +51,12 @@ pub struct ProfQDumpParams {
 /// FIXME(matthewhammer): Determine whether we should include cycle detection here or not.
 #[derive(Clone,Debug)]
 pub enum ProfileQueriesMsg {
+    /// begin a timed pass
+    TimeBegin(String),
+    // end a timed pass
+    TimeEnd,
     /// begin a new query
-    QueryBegin(Span,QueryMsg),
+    QueryBegin(Span, QueryMsg),
     /// query is satisfied by using an already-known value for the given key
     CacheHit,
     /// query requires running a provider; providers may nest, permitting queries to nest.
@@ -110,9 +114,15 @@ pub fn time<T, F>(do_it: bool, what: &str, f: F) -> T where
         r
     });
 
+    if cfg!(debug_assertions) {
+        profq_msg(ProfileQueriesMsg::TimeBegin(what.to_string()))
+    };
     let start = Instant::now();
     let rv = f();
     let dur = start.elapsed();
+    if cfg!(debug_assertions) {
+        profq_msg(ProfileQueriesMsg::TimeEnd)
+    };
 
     print_time_passes_entry_internal(what, dur);
 
index 32e938ebcd616aa9ed482c67de9fbcb8dc9adf04..785efa78ddcd0da1710372121da3ee8777cc85b0 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::time::{Instant};
 use rustc::util::common::{ProfQDumpParams, ProfileQueriesMsg, profq_msg, profq_set_chan};
 use std::sync::mpsc::{Receiver};
 use std::io::{Write};
@@ -41,6 +42,22 @@ pub fn dump(path:String) {
     let _ = rx.recv().unwrap();
 }
 
+// State for parsing recursive trace structure in separate thread, via messages
+#[derive(Clone, Eq, PartialEq)]
+enum ParseState {
+    // No (local) parse state; may be parsing a tree, focused on a
+    // sub-tree that could be anything.
+    Clear,
+    // Have Query information from the last message
+    HaveQuery(trace::Query, Instant),
+    // Have "time-begin" information from the last message (doit flag, and message)
+    HaveTimeBegin(String, Instant),
+}
+struct StackFrame {
+    pub parse_st: ParseState,
+    pub traces:   Vec<trace::Rec>,
+}
+
 // profiling thread; retains state (in local variables) and dump traces, upon request.
 fn profile_queries_thread(r:Receiver<ProfileQueriesMsg>) {
     use self::trace::*;
@@ -48,7 +65,7 @@ fn profile_queries_thread(r:Receiver<ProfileQueriesMsg>) {
     use std::time::{Instant};
 
     let mut profq_msgs : Vec<ProfileQueriesMsg> = vec![];
-    let mut frame : StackFrame = StackFrame{ parse_st:ParseState::NoQuery, traces:vec![] };
+    let mut frame : StackFrame = StackFrame{ parse_st:ParseState::Clear, traces:vec![] };
     let mut stack : Vec<StackFrame> = vec![];
     loop {
         let msg = r.recv();
@@ -64,7 +81,7 @@ fn profile_queries_thread(r:Receiver<ProfileQueriesMsg>) {
             ProfileQueriesMsg::Halt => return,
             ProfileQueriesMsg::Dump(params) => {
                 assert!(stack.len() == 0);
-                assert!(frame.parse_st == trace::ParseState::NoQuery);
+                assert!(frame.parse_st == ParseState::Clear);
                 {
                     // write log of all messages
                     if params.dump_profq_msg_log {
@@ -94,6 +111,10 @@ fn profile_queries_thread(r:Receiver<ProfileQueriesMsg>) {
                     trace::write_traces(&mut html_file, &mut counts_file, &frame.traces);
                     write!(html_file, "</body>\n</html>\n").unwrap();
 
+                    let ack_path = format!("{}.ack", params.path);
+                    let ack_file = File::create(&ack_path).unwrap();
+                    drop(ack_file);
+
                     // Tell main thread that we are done, e.g., so it can exit
                     params.ack.send(()).unwrap();
                 }
@@ -108,22 +129,22 @@ fn profile_queries_thread(r:Receiver<ProfileQueriesMsg>) {
                     (_,ProfileQueriesMsg::Halt) => unreachable!(),
                     (_,ProfileQueriesMsg::Dump(_)) => unreachable!(),
 
-                    // Parse State: NoQuery
-                    (ParseState::NoQuery,
+                    // Parse State: Clear
+                    (ParseState::Clear,
                      ProfileQueriesMsg::QueryBegin(span,querymsg)) => {
                         let start = Instant::now();
                         frame.parse_st = ParseState::HaveQuery
                             (Query{span:span, msg:querymsg}, start)
                     },
-                    (ParseState::NoQuery,
+                    (ParseState::Clear,
                      ProfileQueriesMsg::CacheHit) => {
                         panic!("parse error: unexpected CacheHit; expected QueryBegin")
                     },
-                    (ParseState::NoQuery,
+                    (ParseState::Clear,
                      ProfileQueriesMsg::ProviderBegin) => {
                         panic!("parse error: expected QueryBegin before beginning a provider")
                     },
-                    (ParseState::NoQuery,
+                    (ParseState::Clear,
                      ProfileQueriesMsg::ProviderEnd) => {
                         let provider_extent = frame.traces;
                         match stack.pop() {
@@ -131,12 +152,10 @@ fn profile_queries_thread(r:Receiver<ProfileQueriesMsg>) {
                                 panic!("parse error: expected a stack frame; found an empty stack"),
                             Some(old_frame) => {
                                 match old_frame.parse_st {
-                                    ParseState::NoQuery =>
-                                        panic!("parse error: expected a stack frame for a query"),
-                                    ParseState::HaveQuery(q,start) => {
+                                    ParseState::HaveQuery(q, start) => {
                                         let duration = start.elapsed();
                                         frame = StackFrame{
-                                            parse_st:ParseState::NoQuery,
+                                            parse_st:ParseState::Clear,
                                             traces:old_frame.traces
                                         };
                                         let trace = Rec {
@@ -146,11 +165,66 @@ fn profile_queries_thread(r:Receiver<ProfileQueriesMsg>) {
                                             duration: duration,
                                         };
                                         frame.traces.push( trace );
-                                    }
+                                    },
+                                    _ => panic!("internal parse error: malformed parse stack")
                                 }
                             }
                         }
-                    }
+                   },
+
+
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::TimeBegin(msg)) => {
+                        let start = Instant::now();
+                        frame.parse_st = ParseState::HaveTimeBegin(msg, start);
+                        stack.push(frame);
+                        frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]};
+                    },
+                    (_, ProfileQueriesMsg::TimeBegin(_)) =>
+                        panic!("parse error; did not expect time begin here"),
+
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::TimeEnd) => {
+                        let provider_extent = frame.traces;
+                        match stack.pop() {
+                            None =>
+                                panic!("parse error: expected a stack frame; found an empty stack"),
+                            Some(old_frame) => {
+                                match old_frame.parse_st {
+                                    ParseState::HaveTimeBegin(msg, start) => {
+                                        let duration = start.elapsed();
+                                        frame = StackFrame{
+                                            parse_st:ParseState::Clear,
+                                            traces:old_frame.traces
+                                        };
+                                        let trace = Rec {
+                                            effect: Effect::TimeBegin(msg),
+                                            extent: Box::new(provider_extent),
+                                            start: start,
+                                            duration: duration,
+                                        };
+                                        frame.traces.push( trace );
+                                    },
+                                    _ => panic!("internal parse error: malformed parse stack")
+                                }
+                            }
+                        }
+                    },
+                    (_, ProfileQueriesMsg::TimeEnd) => { panic!("parse error") }
+
+
+                    // Parse State: HaveTimeBegin -- for timing old
+                    // passes in driver (outside of query model, but
+                    // still in use)
+                    (ParseState::HaveTimeBegin(_, _),
+                     ProfileQueriesMsg::ProviderBegin) => {
+                    },
+                    (ParseState::HaveTimeBegin(_, _),
+                     ProfileQueriesMsg::CacheHit) => { unreachable!() },
+                    (ParseState::HaveTimeBegin(_, _),
+                     ProfileQueriesMsg::QueryBegin(_, _)) => { unreachable!() },
+                    (ParseState::HaveTimeBegin(_, _),
+                     ProfileQueriesMsg::ProviderEnd) => { unreachable!() },
 
                     // Parse State: HaveQuery
                     (ParseState::HaveQuery(q,start),
@@ -163,12 +237,12 @@ fn profile_queries_thread(r:Receiver<ProfileQueriesMsg>) {
                             duration: duration,
                         };
                         frame.traces.push( trace );
-                        frame.parse_st = ParseState::NoQuery;
+                        frame.parse_st = ParseState::Clear;
                     },
                     (ParseState::HaveQuery(_,_),
                      ProfileQueriesMsg::ProviderBegin) => {
                         stack.push(frame);
-                        frame = StackFrame{parse_st:ParseState::NoQuery, traces:vec![]};
+                        frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]};
                     },
                     (ParseState::HaveQuery(q,_),
                      ProfileQueriesMsg::ProviderEnd) => {
index c0a8be603cc6943dc294892aba4e39d7d99684c1..8db3a3e2dfa80c156dbadb59c8f15e3975364943 100644 (file)
@@ -22,6 +22,7 @@ pub struct Query {
 }
 pub enum Effect {
     QueryBegin(Query, CacheCase),
+    TimeBegin(String),
 }
 pub enum CacheCase {
     Hit, Miss
@@ -33,16 +34,6 @@ pub struct Rec {
     pub duration: Duration,
     pub extent: Box<Vec<Rec>>,
 }
-/// State for parsing recursive trace structure
-#[derive(Clone, Eq, PartialEq)]
-pub enum ParseState {
-    NoQuery,
-    HaveQuery(Query, Instant),
-}
-pub struct StackFrame {
-    pub parse_st: ParseState,
-    pub traces:   Vec<Rec>,
-}
 pub struct QueryMetric {
     pub count: usize,
     pub duration: Duration,
@@ -58,6 +49,10 @@ pub fn cons_of_query_msg(q: &trace::Query) -> String {
 // First return value is text; second return value is a CSS class
 pub fn html_of_effect(eff: &Effect) -> (String, String) {
     match *eff {
+        Effect::TimeBegin(ref msg) => {
+            (msg.clone(),
+             format!("time-begin"))
+        },
         Effect::QueryBegin(ref qmsg, ref cc) => {
             let cons = cons_of_query_msg(qmsg);
             (cons.clone(),
@@ -142,6 +137,9 @@ fn write_traces_rec(file: &mut File, traces: &Vec<Rec>, total: Duration, depth:
 fn compute_counts_rec(counts: &mut HashMap<String,QueryMetric>, traces: &Vec<Rec>) {
     for t in traces.iter() {
         match t.effect {
+            Effect::TimeBegin(ref _msg) => {
+                // dont count time-begin effects
+            }
             Effect::QueryBegin(ref qmsg, ref _cc) => {
                 let qcons = cons_of_query_msg(qmsg);
                 let qm = match counts.get(&qcons) {
@@ -212,6 +210,12 @@ pub fn write_style(html_file: &mut File) {
 .extent-0 {
     padding: 2px;
 }
+.time-begin {
+    border-width: 4px;
+    font-size: 12px;
+    color: white;
+    border-color: #afa;
+}
 .important {
     border-width: 3px;
     font-size: 12px;
@@ -234,5 +238,30 @@ pub fn write_style(html_file: &mut File) {
 .dur {
   display: none
 }
+.frac-50 {
+  padding: 4px;
+  border-width: 10px;
+  font-size: 16px;
+}
+.frac-40 {
+  padding: 4px;
+  border-width: 8px;
+  font-size: 16px;
+}
+.frac-30 {
+  padding: 3px;
+  border-width: 6px;
+  font-size: 16px;
+}
+.frac-20 {
+  padding: 3px;
+  border-width: 6px;
+  font-size: 16px;
+}
+.frac-10 {
+  padding: 3px;
+  border-width: 6px;
+  font-size: 16px;
+}
 ").unwrap();
 }