Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hooks for thread_profiler. #854

Merged
merged 2 commits into from Feb 10, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -25,6 +25,7 @@ script:
- (cd webrender_traits && cargo test --verbose)
- (cd webrender && cargo test --verbose)
- (cd sample && cargo test --verbose)
- (cd sample && cargo build --verbose --features=profiler)
- (cd wrench && cargo test --verbose)
- (cd wrench && cargo build --release --verbose --features headless)
- (cd wrench && python run_tests.py res/rect.yaml)

Some generated files are not rendered by default. Learn more.

@@ -12,6 +12,9 @@ path = "../webrender"
path = "../webrender_traits"
default_features = false

[features]
profiler = [ "webrender/profiler" ]

[dependencies]
app_units = "0.3"
euclid = "0.10"
@@ -12,6 +12,7 @@ default = ["codegen", "freetype-lib"]
codegen = ["webrender_traits/codegen"]
freetype-lib = ["freetype/servo-freetype-sys"]
serde_derive = ["webrender_traits/serde_derive"]
profiler = ["thread_profiler/thread_profiler"]

[dependencies]
app_units = "0.3"
@@ -30,6 +31,7 @@ threadpool = "1.3.2"
webrender_traits = {path = "../webrender_traits", default-features = false}
bitflags = "0.7"
gamma-lut = "0.1"
thread_profiler = "0.1"

[dev-dependencies]
angle = {git = "https://github.com/servo/angle", branch = "servo"}
@@ -653,6 +653,7 @@ impl FrameBuilder {
resource_cache: &mut ResourceCache,
profile_counters: &mut FrameProfileCounters,
device_pixel_ratio: f32) {
profile_scope!("cull");
LayerRectCalculationAndCullingPass::create_and_run(self,
screen_rect,
scroll_tree,
@@ -708,6 +709,8 @@ impl FrameBuilder {
}

fn build_render_task(&self) -> (RenderTask, usize) {
profile_scope!("build_render_task");

let mut next_z = 0;
let mut next_task_index = RenderTaskIndex(0);

@@ -833,6 +836,8 @@ impl FrameBuilder {
scroll_tree: &ScrollTree,
auxiliary_lists_map: &AuxiliaryListsMap,
device_pixel_ratio: f32) -> Frame {
profile_scope!("build");

let mut profile_counters = FrameProfileCounters::new();
profile_counters.total_primitives.set(self.prim_store.prim_count());

@@ -48,6 +48,8 @@ extern crate lazy_static;
extern crate log;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate thread_profiler;

mod batch_builder;
mod debug_colors;
@@ -42,7 +42,6 @@ fn float_to_fixed_ft(f: f64) -> i32 {

impl FontContext {
pub fn new() -> FontContext {
// let _pf = util::ProfileScope::new(" FontContext::new");
let mut lib: FT_Library = ptr::null_mut();
unsafe {
let result = FT_Init_FreeType(&mut lib);
@@ -848,6 +848,7 @@ impl PrimitiveStore {
pub fn resolve_primitives(&mut self,
resource_cache: &ResourceCache,
device_pixel_ratio: f32) -> Vec<DeferredResolve> {
profile_scope!("resolve_primitives");
let mut deferred_resolves = Vec::new();

for prim_index in self.prims_to_resolve.drain(..) {
@@ -16,6 +16,7 @@ use std::io::{Cursor, Read};
use std::sync::{Arc, Mutex};
use std::sync::mpsc::Sender;
use texture_cache::TextureCache;
use thread_profiler::register_thread_with_profiler;
use webrender_traits::{ApiMsg, AuxiliaryLists, BuiltDisplayList, IdNamespace, ImageData};
use webrender_traits::{PipelineId, RenderNotifier, RenderDispatcher, WebGLCommand, WebGLContextId};
use webrender_traits::channel::{PayloadHelperMethods, PayloadReceiver, PayloadSender, MsgReceiver};
@@ -70,6 +71,8 @@ impl RenderBackend {
let resource_cache = ResourceCache::new(texture_cache,
enable_aa);

register_thread_with_profiler("Backend".to_string());

RenderBackend {
api_rx: api_rx,
payload_rx: payload_rx,
@@ -97,6 +100,7 @@ impl RenderBackend {

loop {
let msg = self.api_rx.recv();
profile_scope!("handle_msg");
match msg {
Ok(msg) => {
if let Some(ref mut r) = self.recorder {
@@ -147,6 +151,7 @@ impl RenderBackend {
display_list_descriptor,
auxiliary_lists_descriptor,
preserve_frame_state) => {
profile_scope!("SetRootDisplayList");
let mut leftover_auxiliary_data = vec![];
let mut auxiliary_data;
loop {
@@ -195,6 +200,7 @@ impl RenderBackend {
self.build_scene();
}
ApiMsg::SetRootPipeline(pipeline_id) => {
profile_scope!("SetRootPipeline");
self.scene.set_root_pipeline_id(pipeline_id);

if self.scene.display_lists.get(&pipeline_id).is_none() {
@@ -204,6 +210,7 @@ impl RenderBackend {
self.build_scene();
}
ApiMsg::Scroll(delta, cursor, move_phase) => {
profile_scope!("Scroll");
let frame = profile_counters.total_time.profile(|| {
if self.frame.scroll(delta, cursor, move_phase) {
Some(self.render())
@@ -221,6 +228,7 @@ impl RenderBackend {
}
}
ApiMsg::ScrollLayersWithScrollId(origin, pipeline_id, scroll_root_id) => {
profile_scope!("ScrollLayersWithScrollId");
let frame = profile_counters.total_time.profile(|| {
if self.frame.scroll_layers(origin, pipeline_id, scroll_root_id) {
Some(self.render())
@@ -239,6 +247,7 @@ impl RenderBackend {

}
ApiMsg::TickScrollingBounce => {
profile_scope!("TickScrollingBounce");
let frame = profile_counters.total_time.profile(|| {
self.frame.tick_scrolling_bounce_animations();
self.render()
@@ -250,6 +259,7 @@ impl RenderBackend {
panic!("unused api - remove from webrender_traits");
}
ApiMsg::GetScrollLayerState(tx) => {
profile_scope!("GetScrollLayerState");
tx.send(self.frame.get_scroll_layer_state())
.unwrap()
}
@@ -317,6 +327,8 @@ impl RenderBackend {
self.handle_vr_compositor_command(context_id, command);
}
ApiMsg::GenerateFrame(property_bindings) => {
profile_scope!("GenerateFrame");

// Ideally, when there are property bindings present,
// we won't need to rebuild the entire frame here.
// However, to avoid conflicts with the ongoing work to
@@ -42,6 +42,7 @@ use texture_cache::TextureCache;
use tiling::{AlphaBatchKind, BlurCommand, Frame, PrimitiveBatch, PrimitiveBatchData};
use tiling::{CacheClipInstance, PrimitiveInstance, RenderTarget};
use time::precise_time_ns;
use thread_profiler::{register_thread_with_profiler, write_profile};
use util::TransformedRectKind;
use webrender_traits::{ColorF, Epoch, PipelineId, RenderNotifier, RenderDispatcher};
use webrender_traits::{ExternalImageId, ImageData, ImageFormat, RenderApiSender, RendererKind};
@@ -504,6 +505,8 @@ impl Renderer {
let (payload_tx, payload_rx) = try!{ channel::payload_channel() };
let (result_tx, result_rx) = channel();

register_thread_with_profiler("Compositor".to_owned());

let notifier = Arc::new(Mutex::new(None));

let file_watch_handler = FileWatcher {
@@ -869,6 +872,8 @@ impl Renderer {
///
/// Should be called before `render()`, as texture cache updates are done here.
pub fn update(&mut self) {
profile_scope!("update");

// Pull any pending results and return the most recent.
while let Ok(msg) = self.result_rx.try_recv() {
match msg {
@@ -926,6 +931,8 @@ impl Renderer {
/// A Frame is supplied by calling [set_root_stacking_context()][newframe].
/// [newframe]: ../../webrender_traits/struct.RenderApi.html#method.set_root_stacking_context
pub fn render(&mut self, framebuffer_size: DeviceUintSize) {
profile_scope!("render");

if let Some(mut frame) = self.current_frame.take() {
if let Some(ref mut frame) = frame.frame {
let mut profile_timers = RendererProfileTimers::new();
@@ -1632,6 +1639,10 @@ impl Renderer {
self.enable_profiler = enabled;
}

pub fn save_cpu_profile(&self, filename: &str) {
write_profile(filename);
}

fn draw_render_target_debug(&mut self,
framebuffer_size: &DeviceUintSize) {
if self.render_target_debug {
@@ -19,6 +19,7 @@ use std::sync::{Arc, Barrier};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;
use texture_cache::{TextureCache, TextureCacheItemId};
use thread_profiler::register_thread_with_profiler;
use webrender_traits::{Epoch, FontKey, GlyphKey, ImageKey, ImageFormat, ImageRendering};
use webrender_traits::{FontRenderMode, ImageData, GlyphDimensions, WebGLContextId};
use webrender_traits::{DevicePoint, DeviceIntSize, ImageDescriptor, ColorF};
@@ -486,6 +487,8 @@ impl ResourceCache {
}

pub fn block_until_all_resources_added(&mut self) {
profile_scope!("block_until_all_resources_added");

debug_assert!(self.state == State::AddResources);
self.state = State::QueryResources;

@@ -637,6 +640,17 @@ fn spawn_glyph_cache_thread() -> (Sender<GlyphCacheMsg>, Receiver<GlyphCacheResu
let mut glyph_cache = None;
let mut current_frame_id = FrameId(0);

register_thread_with_profiler("GlyphCache".to_string());

let barrier = Arc::new(Barrier::new(worker_count));
for i in 0..worker_count {
let barrier = barrier.clone();
thread_pool.execute(move || {
register_thread_with_profiler(format!("Glyph Worker {}", i));
barrier.wait();
});
}

// Maintain a set of glyphs that have been requested this
// frame. This ensures the glyph thread won't rasterize
// the same glyph more than once in a frame. This is required
@@ -646,15 +660,20 @@ fn spawn_glyph_cache_thread() -> (Sender<GlyphCacheMsg>, Receiver<GlyphCacheResu
let mut pending_glyphs = HashSet::new();

while let Ok(msg) = msg_rx.recv() {
profile_scope!("handle_msg");
match msg {
GlyphCacheMsg::BeginFrame(frame_id, cache) => {
profile_scope!("BeginFrame");

// We are beginning a new frame. Take ownership of the glyph
// cache hash map, so we can easily see which glyph requests
// actually need to be rasterized.
current_frame_id = frame_id;
glyph_cache = Some(cache);
}
GlyphCacheMsg::AddFont(font_key, font_template) => {
profile_scope!("AddFont");

// Add a new font to the font context in each worker thread.
// Use a barrier to ensure that each worker in the pool handles
// one of these messages, to ensure that the new font gets
@@ -682,6 +701,8 @@ fn spawn_glyph_cache_thread() -> (Sender<GlyphCacheMsg>, Receiver<GlyphCacheResu
}
}
GlyphCacheMsg::RequestGlyphs(key, size, color, glyph_instances, render_mode, glyph_options) => {
profile_scope!("RequestGlyphs");

// Request some glyphs for a text run.
// For any glyph that isn't currently in the cache,
// immeediately push a job to the worker thread pool
@@ -703,6 +724,7 @@ fn spawn_glyph_cache_thread() -> (Sender<GlyphCacheMsg>, Receiver<GlyphCacheResu
let glyph_tx = glyph_tx.clone();
pending_glyphs.insert(glyph_key.clone());
thread_pool.execute(move || {
profile_scope!("glyph");
FONT_CONTEXT.with(move |font_context| {
let mut font_context = font_context.borrow_mut();
let result = font_context.rasterize_glyph(&glyph_key.key,
@@ -715,6 +737,8 @@ fn spawn_glyph_cache_thread() -> (Sender<GlyphCacheMsg>, Receiver<GlyphCacheResu
}
}
GlyphCacheMsg::EndFrame => {
profile_scope!("EndFrame");

// The resource cache has finished requesting glyphs. Block
// on completion of any pending glyph rasterizing jobs, and then
// return the list of new glyphs to the resource cache.
@@ -1001,6 +1001,8 @@ impl RenderPass {


pub fn build(&mut self, ctx: &RenderTargetContext, render_tasks: &mut RenderTaskCollection) {
profile_scope!("RenderPass::build");

// Step through each task, adding to batches as appropriate.
let tasks = mem::replace(&mut self.tasks, Vec::new());
for mut task in tasks {
@@ -7,31 +7,6 @@ use euclid::{TypedRect, TypedPoint2D, TypedSize2D, TypedPoint4D, TypedMatrix4D};
use webrender_traits::{DeviceIntRect, DeviceIntPoint, DeviceIntSize};
use webrender_traits::{LayerRect, WorldPoint4D, LayerPoint4D, LayerToWorldTransform};
use num_traits::Zero;
use time::precise_time_ns;

#[allow(dead_code)]
pub struct ProfileScope {
name: &'static str,
t0: u64,
}

impl ProfileScope {
#[allow(dead_code)]
pub fn new(name: &'static str) -> ProfileScope {
ProfileScope {
name: name,
t0: precise_time_ns(),
}
}
}

impl Drop for ProfileScope {
fn drop(&mut self) {
let t1 = precise_time_ns();
let ms = (t1 - self.t0) as f64 / 1000000f64;
println!("{} {}", self.name, ms);
}
}

// TODO: Implement these in euclid!
pub trait MatrixHelpers<Src, Dst> {
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.