aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/layout_task.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout/layout_task.rs')
-rw-r--r--components/layout/layout_task.rs54
1 files changed, 52 insertions, 2 deletions
diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs
index 5d1ab5781f8..d8c09a18218 100644
--- a/components/layout/layout_task.rs
+++ b/components/layout/layout_task.rs
@@ -56,6 +56,8 @@ use net::resource_task::{ResourceTask, load_bytes_iter};
use util::cursor::Cursor;
use util::geometry::Au;
use util::logical_geometry::LogicalPoint;
+use util::memory::{MemoryProfilerChan, MemoryProfilerMsg, MemoryReport, MemoryReportsChan};
+use util::memory::{SizeOf};
use util::opts;
use util::smallvec::{SmallVec, SmallVec1, VecLike};
use util::task::spawn_named_with_send_on_failure;
@@ -117,6 +119,9 @@ pub struct LayoutTask {
/// The ID of the pipeline that we belong to.
pub id: PipelineId,
+ /// The URL of the pipeline that we belong to.
+ pub url: Url,
+
/// The port on which we receive messages from the script task.
pub port: Receiver<Msg>,
@@ -138,6 +143,12 @@ pub struct LayoutTask {
/// The channel on which messages can be sent to the time profiler.
pub time_profiler_chan: TimeProfilerChan,
+ /// The channel on which messages can be sent to the memory profiler.
+ pub memory_profiler_chan: MemoryProfilerChan,
+
+ /// The name used for the task's memory reporter.
+ pub memory_reporter_name: String,
+
/// The channel on which messages can be sent to the resource task.
pub resource_task: ResourceTask,
@@ -181,6 +192,7 @@ impl LayoutTaskFactory for LayoutTask {
/// Spawns a new layout task.
fn create(_phantom: Option<&mut LayoutTask>,
id: PipelineId,
+ url: Url,
chan: OpaqueScriptLayoutChannel,
pipeline_port: Receiver<LayoutControlMsg>,
constellation_chan: ConstellationChan,
@@ -191,6 +203,7 @@ impl LayoutTaskFactory for LayoutTask {
img_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask,
time_profiler_chan: TimeProfilerChan,
+ memory_profiler_chan: MemoryProfilerChan,
shutdown_chan: Sender<()>) {
let ConstellationChan(con_chan) = constellation_chan.clone();
spawn_named_with_send_on_failure("LayoutTask", task_state::LAYOUT, move || {
@@ -199,6 +212,7 @@ impl LayoutTaskFactory for LayoutTask {
let layout =
LayoutTask::new(
id,
+ url,
chan.receiver(),
LayoutChan(sender),
pipeline_port,
@@ -208,7 +222,8 @@ impl LayoutTaskFactory for LayoutTask {
resource_task,
img_cache_task,
font_cache_task,
- time_profiler_chan);
+ time_profiler_chan,
+ memory_profiler_chan);
layout.start();
}
shutdown_chan.send(()).unwrap();
@@ -249,6 +264,7 @@ impl<'a> DerefMut for RWGuard<'a> {
impl LayoutTask {
/// Creates a new `LayoutTask` structure.
fn new(id: PipelineId,
+ url: Url,
port: Receiver<Msg>,
chan: LayoutChan,
pipeline_port: Receiver<LayoutControlMsg>,
@@ -258,7 +274,8 @@ impl LayoutTask {
resource_task: ResourceTask,
image_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask,
- time_profiler_chan: TimeProfilerChan)
+ time_profiler_chan: TimeProfilerChan,
+ memory_profiler_chan: MemoryProfilerChan)
-> LayoutTask {
let local_image_cache =
Arc::new(Mutex::new(LocalImageCache::new(image_cache_task.clone())));
@@ -271,8 +288,15 @@ impl LayoutTask {
None
};
+ // Register this thread as a memory reporter, via its own channel.
+ let reporter = Box::new(chan.clone());
+ let reporter_name = format!("layout-reporter-{}", id.0);
+ memory_profiler_chan.send(MemoryProfilerMsg::RegisterMemoryReporter(reporter_name.clone(),
+ reporter));
+
LayoutTask {
id: id,
+ url: url,
port: port,
pipeline_port: pipeline_port,
chan: chan,
@@ -280,6 +304,8 @@ impl LayoutTask {
constellation_chan: constellation_chan.clone(),
paint_chan: paint_chan,
time_profiler_chan: time_profiler_chan,
+ memory_profiler_chan: memory_profiler_chan,
+ memory_reporter_name: reporter_name,
resource_task: resource_task,
image_cache_task: image_cache_task.clone(),
font_cache_task: font_cache_task,
@@ -423,6 +449,9 @@ impl LayoutTask {
self.handle_reap_layout_data(dead_layout_data)
}
},
+ Msg::CollectMemoryReports(reports_chan) => {
+ self.collect_memory_reports(reports_chan, possibly_locked_rw_data);
+ },
Msg::PrepareToExit(response_chan) => {
debug!("layout: PrepareToExitMsg received");
self.prepare_to_exit(response_chan, possibly_locked_rw_data);
@@ -438,6 +467,23 @@ impl LayoutTask {
true
}
+ fn collect_memory_reports<'a>(&'a self,
+ reports_chan: MemoryReportsChan,
+ possibly_locked_rw_data:
+ &mut Option<MutexGuard<'a, LayoutTaskData>>) {
+ let mut reports = vec![];
+
+ // FIXME(njn): Just measuring the display tree for now.
+ let rw_data = self.lock_rw_data(possibly_locked_rw_data);
+ let stacking_context = rw_data.stacking_context.as_ref();
+ reports.push(MemoryReport {
+ name: format!("display-list::{}", self.url),
+ size: stacking_context.map_or(0, |sc| sc.size_of_excluding_self() as u64),
+ });
+
+ reports_chan.send(reports);
+ }
+
/// Enters a quiescent state in which no new messages except for `layout_interface::Msg::ReapLayoutData` will be
/// processed until an `ExitNowMsg` is received. A pong is immediately sent on the given
/// response channel.
@@ -481,6 +527,10 @@ impl LayoutTask {
LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data);
}
+ let unregister_msg =
+ MemoryProfilerMsg::UnregisterMemoryReporter(self.memory_reporter_name.clone());
+ self.memory_profiler_chan.send(unregister_msg);
+
self.paint_chan.send(PaintMsg::Exit(Some(response_chan), exit_type));
response_port.recv().unwrap()
}