mirror of
https://github.com/servo/servo.git
synced 2025-06-24 09:04:33 +01:00
infrastructure. With this change, if you supply the `-Z signpost` flag, Instruments.app can display Servo events overlaid with callstack data. Even better, you can get call stack profiling for individual Servo events (one layout, one network request, one style recalculation, etc.) This adds a dependency on the `signpost` crate. On unsupported OS's, this crate is an no-op.
142 lines
4.3 KiB
Rust
142 lines
4.3 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
extern crate time as std_time;
|
|
|
|
use energy::read_energy_uj;
|
|
use ipc_channel::ipc::IpcSender;
|
|
use self::std_time::precise_time_ns;
|
|
use signpost;
|
|
use util::opts;
|
|
|
|
#[derive(PartialEq, Clone, PartialOrd, Eq, Ord, Debug, Deserialize, Serialize)]
|
|
pub struct TimerMetadata {
|
|
pub url: String,
|
|
pub iframe: TimerMetadataFrameType,
|
|
pub incremental: TimerMetadataReflowType,
|
|
}
|
|
|
|
#[derive(Clone, Deserialize, Serialize)]
|
|
pub struct ProfilerChan(pub IpcSender<ProfilerMsg>);
|
|
|
|
impl ProfilerChan {
|
|
pub fn send(&self, msg: ProfilerMsg) {
|
|
self.0.send(msg).unwrap();
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Deserialize, Serialize)]
|
|
pub enum ProfilerMsg {
|
|
/// Normal message used for reporting time
|
|
Time((ProfilerCategory, Option<TimerMetadata>), (u64, u64), (u64, u64)),
|
|
/// Message used to force print the profiling metrics
|
|
Print,
|
|
/// Tells the profiler to shut down.
|
|
Exit(IpcSender<()>),
|
|
}
|
|
|
|
#[repr(u32)]
|
|
#[derive(PartialEq, Clone, Copy, PartialOrd, Eq, Ord, Deserialize, Serialize, Debug, Hash)]
|
|
pub enum ProfilerCategory {
|
|
Compositing = 0x00,
|
|
LayoutPerform = 0x10,
|
|
LayoutStyleRecalc = 0x11,
|
|
LayoutTextShaping = 0x12,
|
|
LayoutRestyleDamagePropagation = 0x13,
|
|
LayoutNonIncrementalReset = 0x14,
|
|
LayoutSelectorMatch = 0x15,
|
|
LayoutTreeBuilder = 0x16,
|
|
LayoutDamagePropagate = 0x17,
|
|
LayoutGeneratedContent = 0x18,
|
|
LayoutDisplayListSorting = 0x19,
|
|
LayoutFloatPlacementSpeculation = 0x1a,
|
|
LayoutMain = 0x1b,
|
|
LayoutStoreOverflow = 0x1c,
|
|
LayoutParallelWarmup = 0x1d,
|
|
LayoutDispListBuild = 0x1e,
|
|
NetHTTPRequestResponse = 0x30,
|
|
PaintingPerTile = 0x41,
|
|
PaintingPrepBuff = 0x42,
|
|
Painting = 0x43,
|
|
ImageDecoding = 0x50,
|
|
ImageSaving = 0x51,
|
|
ScriptAttachLayout = 0x60,
|
|
ScriptConstellationMsg = 0x61,
|
|
ScriptDevtoolsMsg = 0x62,
|
|
ScriptDocumentEvent = 0x63,
|
|
ScriptDomEvent = 0x64,
|
|
ScriptEvaluate = 0x65,
|
|
ScriptEvent = 0x66,
|
|
ScriptFileRead = 0x67,
|
|
ScriptImageCacheMsg = 0x68,
|
|
ScriptInputEvent = 0x69,
|
|
ScriptNetworkEvent = 0x6a,
|
|
ScriptParseHTML = 0x6b,
|
|
ScriptPlannedNavigation = 0x6c,
|
|
ScriptResize = 0x6d,
|
|
ScriptSetScrollState = 0x6e,
|
|
ScriptSetViewport = 0x6f,
|
|
ScriptTimerEvent = 0x70,
|
|
ScriptStylesheetLoad = 0x71,
|
|
ScriptUpdateReplacedElement = 0x72,
|
|
ScriptWebSocketEvent = 0x73,
|
|
ScriptWorkerEvent = 0x74,
|
|
ScriptServiceWorkerEvent = 0x75,
|
|
ApplicationHeartbeat = 0x90,
|
|
}
|
|
|
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Deserialize, Serialize)]
|
|
pub enum TimerMetadataFrameType {
|
|
RootWindow,
|
|
IFrame,
|
|
}
|
|
|
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Deserialize, Serialize)]
|
|
pub enum TimerMetadataReflowType {
|
|
Incremental,
|
|
FirstReflow,
|
|
}
|
|
|
|
pub fn profile<T, F>(category: ProfilerCategory,
|
|
meta: Option<TimerMetadata>,
|
|
profiler_chan: ProfilerChan,
|
|
callback: F)
|
|
-> T
|
|
where F: FnOnce() -> T
|
|
{
|
|
if opts::get().signpost {
|
|
signpost::start(category as u32, &[0, 0, 0, (category as usize) >> 4]);
|
|
}
|
|
let start_energy = read_energy_uj();
|
|
let start_time = precise_time_ns();
|
|
|
|
let val = callback();
|
|
|
|
let end_time = precise_time_ns();
|
|
let end_energy = read_energy_uj();
|
|
if opts::get().signpost {
|
|
signpost::end(category as u32, &[0, 0, 0, (category as usize) >> 4]);
|
|
}
|
|
|
|
send_profile_data(category,
|
|
meta,
|
|
profiler_chan,
|
|
start_time,
|
|
end_time,
|
|
start_energy,
|
|
end_energy);
|
|
val
|
|
}
|
|
|
|
pub fn send_profile_data(category: ProfilerCategory,
|
|
meta: Option<TimerMetadata>,
|
|
profiler_chan: ProfilerChan,
|
|
start_time: u64,
|
|
end_time: u64,
|
|
start_energy: u64,
|
|
end_energy: u64) {
|
|
profiler_chan.send(ProfilerMsg::Time((category, meta),
|
|
(start_time, end_time),
|
|
(start_energy, end_energy)));
|
|
}
|