diff --git a/components/background_hang_monitor/background_hang_monitor.rs b/components/background_hang_monitor/background_hang_monitor.rs index 1ed55e463b6..abd974f658a 100644 --- a/components/background_hang_monitor/background_hang_monitor.rs +++ b/components/background_hang_monitor/background_hang_monitor.rs @@ -12,7 +12,7 @@ use msg::constellation_msg::{ }; use msg::constellation_msg::{HangAlert, HangAnnotation, HangMonitorAlert, SamplerControlMsg}; use std::cell::Cell; -use std::collections::HashMap; +use std::collections::{HashMap, VecDeque}; use std::thread; use std::time::{Duration, Instant}; @@ -153,10 +153,11 @@ pub struct BackgroundHangMonitorWorker { port: Receiver<(MonitoredComponentId, MonitoredComponentMsg)>, control_port: Receiver, sampling_duration: Option, + sampling_max_duration: Option, last_sample: Instant, creation: Instant, sampling_baseline: Instant, - samples: Vec, + samples: VecDeque, } impl BackgroundHangMonitorWorker { @@ -173,10 +174,11 @@ impl BackgroundHangMonitorWorker { port, control_port, sampling_duration: None, + sampling_max_duration: None, last_sample: Instant::now(), sampling_baseline: Instant::now(), creation: Instant::now(), - samples: vec![], + samples: Default::default(), } } @@ -239,9 +241,10 @@ impl BackgroundHangMonitorWorker { }, recv(self.control_port) -> event => { match event { - Ok(SamplerControlMsg::Enable(rate)) => { + Ok(SamplerControlMsg::Enable(rate, max_duration)) => { println!("Enabling profiler."); self.sampling_duration = Some(rate); + self.sampling_max_duration = Some(max_duration); self.sampling_baseline = Instant::now(); None } @@ -381,9 +384,15 @@ impl BackgroundHangMonitorWorker { for (component_id, monitored) in self.monitored_components.iter_mut() { let instant = Instant::now(); if let Ok(stack) = monitored.sampler.suspend_and_sample_thread() { - // TODO: support a bounded buffer that discards older samples. + if self.sampling_baseline.elapsed() > + self.sampling_max_duration + .expect("Max duration has been set") + { + // Buffer is full, start discarding older samples. + self.samples.pop_front(); + } self.samples - .push(Sample(component_id.clone(), instant, stack)); + .push_back(Sample(component_id.clone(), instant, stack)); } } } diff --git a/components/background_hang_monitor/tests/hang_monitor_tests.rs b/components/background_hang_monitor/tests/hang_monitor_tests.rs index 2ecb526e152..5b04334a962 100644 --- a/components/background_hang_monitor/tests/hang_monitor_tests.rs +++ b/components/background_hang_monitor/tests/hang_monitor_tests.rs @@ -30,11 +30,15 @@ fn test_sampler() { ); const RATE: u64 = 10; + const MAX_DURATION: u64 = 10; sampler_sender - .send(SamplerControlMsg::Enable(Duration::from_millis(RATE))) + .send(SamplerControlMsg::Enable( + Duration::from_millis(RATE), + Duration::from_secs(MAX_DURATION), + )) .unwrap(); - thread::sleep(Duration::from_millis(30)); + thread::sleep(Duration::from_millis(100)); sampler_sender.send(SamplerControlMsg::Disable).unwrap(); diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index 7648cb7ee59..7afcdde9a47 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -95,8 +95,8 @@ pub enum WindowEvent { ToggleWebRenderDebug(WebRenderDebugOption), /// Capture current WebRender CaptureWebRender, - /// Toggle sampling profiler with the given sampling rate - ToggleSamplingProfiler(Duration), + /// Toggle sampling profiler with the given sampling rate and max duration. + ToggleSamplingProfiler(Duration, Duration), } impl Debug for WindowEvent { diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 7e60dc869af..3b440bdde82 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -1216,9 +1216,9 @@ where self.forward_event(destination_pipeline_id, event); }, FromCompositorMsg::SetCursor(cursor) => self.handle_set_cursor_msg(cursor), - FromCompositorMsg::EnableProfiler(rate) => { + FromCompositorMsg::EnableProfiler(rate, max_duration) => { for chan in &self.sampling_profiler_control { - if let Err(e) = chan.send(SamplerControlMsg::Enable(rate)) { + if let Err(e) = chan.send(SamplerControlMsg::Enable(rate, max_duration)) { warn!("error communicating with sampling profiler: {}", e); } } diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index 04aa13b483f..aa61491afa5 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -494,6 +494,7 @@ pub trait BackgroundHangMonitor { /// Messages to control the sampling profiler. #[derive(Deserialize, Serialize)] pub enum SamplerControlMsg { - Enable(Duration), + /// Enable the sampler, with a given sampling rate and max total sampling duration. + Enable(Duration, Duration), Disable, } diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 49f4f055e63..6c5f6500a5a 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -778,8 +778,8 @@ pub enum ConstellationMsg { ForwardEvent(PipelineId, CompositorEvent), /// Requesting a change to the onscreen cursor. SetCursor(Cursor), - /// Enable the sampling profiler. - EnableProfiler(Duration), + /// Enable the sampling profiler, with a given sampling rate and max total sampling duration. + EnableProfiler(Duration, Duration), /// Disable the sampling profiler. DisableProfiler, } diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 71848f165a0..2e3b7c8082b 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -408,10 +408,10 @@ where } }, - WindowEvent::ToggleSamplingProfiler(rate) => { + WindowEvent::ToggleSamplingProfiler(rate, max_duration) => { self.profiler_enabled = !self.profiler_enabled; let msg = if self.profiler_enabled { - ConstellationMsg::EnableProfiler(rate) + ConstellationMsg::EnableProfiler(rate, max_duration) } else { ConstellationMsg::DisableProfiler }; diff --git a/ports/servo/browser.rs b/ports/servo/browser.rs index 221136100fe..52c2ed19662 100644 --- a/ports/servo/browser.rs +++ b/ports/servo/browser.rs @@ -121,8 +121,12 @@ impl Browser { .ok() .and_then(|s| s.parse().ok()) .unwrap_or(10); + let duration = env::var("SAMPLING_DURATION") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(10); self.event_queue.push(WindowEvent::ToggleSamplingProfiler( - Duration::from_millis(rate))); + Duration::from_millis(rate), Duration::from_secs(duration))); }) .shortcut(Modifiers::CONTROL, Key::F9, || { self.event_queue.push(WindowEvent::CaptureWebRender)