mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Pass new method in CollectServoSizes for accurate DOM heap use reporting
This commit is contained in:
parent
97c12bd392
commit
7f7fc91758
7 changed files with 47 additions and 53 deletions
|
@ -52,6 +52,7 @@ hyper = "0.10"
|
|||
hyper_serde = "0.8"
|
||||
image = "0.18"
|
||||
ipc-channel = "0.10"
|
||||
itertools = "0.7.6"
|
||||
jstraceable_derive = {path = "../jstraceable_derive"}
|
||||
lazy_static = "1"
|
||||
libc = "0.2"
|
||||
|
@ -62,7 +63,7 @@ metrics = {path = "../metrics"}
|
|||
mitochondria = "1.1.2"
|
||||
mime = "0.2.1"
|
||||
mime_guess = "1.8.0"
|
||||
mozjs = { version = "0.4", features = ["promises"]}
|
||||
mozjs = { version = "0.5.0", features = ["promises"]}
|
||||
msg = {path = "../msg"}
|
||||
net_traits = {path = "../net_traits"}
|
||||
num-traits = "0.1.32"
|
||||
|
|
|
@ -107,7 +107,6 @@ extern crate xml5ever;
|
|||
|
||||
#[macro_use]
|
||||
mod task;
|
||||
|
||||
mod body;
|
||||
pub mod clipboard_provider;
|
||||
mod devtools;
|
||||
|
@ -150,7 +149,10 @@ pub mod layout_exports {
|
|||
}
|
||||
|
||||
use dom::bindings::codegen::RegisterBindings;
|
||||
use dom::bindings::conversions::is_dom_proxy;
|
||||
use dom::bindings::proxyhandler;
|
||||
use dom::bindings::utils::is_platform_object;
|
||||
use js::jsapi::JSObject;
|
||||
use script_traits::SWManagerSenders;
|
||||
use serviceworker_manager::ServiceWorkerManager;
|
||||
|
||||
|
@ -200,6 +202,11 @@ pub fn init_service_workers(sw_senders: SWManagerSenders) {
|
|||
ServiceWorkerManager::spawn_manager(sw_senders);
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern "C" fn is_dom_object(obj: *mut JSObject) -> bool {
|
||||
!obj.is_null() && (is_platform_object(obj) || is_dom_proxy(obj))
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub fn init() {
|
||||
unsafe {
|
||||
|
@ -208,6 +215,8 @@ pub fn init() {
|
|||
// Create the global vtables used by the (generated) DOM
|
||||
// bindings to implement JS proxies.
|
||||
RegisterBindings::RegisterProxyHandlers();
|
||||
|
||||
js::glue::InitializeMemoryReporter(Some(is_dom_object));
|
||||
}
|
||||
|
||||
perform_platform_specific_initialization();
|
||||
|
|
|
@ -4,24 +4,9 @@
|
|||
|
||||
//! Routines for handling measuring the memory usage of arbitrary DOM nodes.
|
||||
|
||||
use dom::bindings::conversions::get_dom_class;
|
||||
use dom::bindings::reflector::DomObject;
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||
use std::os::raw::c_void;
|
||||
|
||||
// This is equivalent to measuring a Box<T>, except that DOM objects lose their
|
||||
// associated box in order to stash their pointers in a reserved slot of their
|
||||
// JS reflector.
|
||||
#[allow(unsafe_code)]
|
||||
pub fn malloc_size_of_including_self<T: DomObject + MallocSizeOf>(
|
||||
ops: &mut MallocSizeOfOps, obj: &T) -> usize
|
||||
{
|
||||
unsafe {
|
||||
let class = get_dom_class(obj.reflector().get_jsobject().get()).unwrap();
|
||||
(class.malloc_size_of)(ops, obj as *const T as *const c_void)
|
||||
}
|
||||
}
|
||||
|
||||
/// Used by codegen to include the pointer to the `MallocSizeOf` implementation of each
|
||||
/// IDL interface. This way we don't have to find the most-derived interface of DOM
|
||||
/// objects by hand in code.
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
//! script thread, the dom, and the worker threads.
|
||||
|
||||
use dom::bindings::codegen::Bindings::PromiseBinding::PromiseJobCallback;
|
||||
use dom::bindings::conversions::get_dom_class;
|
||||
use dom::bindings::conversions::private_from_object;
|
||||
use dom::bindings::refcounted::{LiveDOMReferences, trace_refcounted_objects};
|
||||
use dom::bindings::root::trace_roots;
|
||||
use dom::bindings::settings_stack;
|
||||
|
@ -21,6 +23,7 @@ use js::jsapi::{JSJitCompilerOption, JS_SetOffthreadIonCompilationEnabled, JS_Se
|
|||
use js::jsapi::{JSObject, RuntimeOptionsRef, SetPreserveWrapperCallback, SetEnqueuePromiseJobCallback};
|
||||
use js::panic::wrap_panic;
|
||||
use js::rust::Runtime as RustRuntime;
|
||||
use malloc_size_of::MallocSizeOfOps;
|
||||
use microtask::{EnqueuedPromiseCallback, Microtask};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use profile_traits::mem::{Report, ReportKind, ReportsChan};
|
||||
|
@ -312,6 +315,24 @@ pub unsafe fn new_rt_and_cx() -> Runtime {
|
|||
Runtime(runtime)
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
unsafe extern "C" fn get_size(obj: *mut JSObject) -> usize {
|
||||
match get_dom_class(obj) {
|
||||
Ok(v) => {
|
||||
let dom_object = private_from_object(obj) as *const c_void;
|
||||
|
||||
if dom_object.is_null() {
|
||||
return 0;
|
||||
}
|
||||
let mut ops = MallocSizeOfOps::new(::servo_allocator::usable_size, None, None);
|
||||
(v.malloc_size_of)(&mut ops, dom_object)
|
||||
}
|
||||
Err(_e) => {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
pub fn get_reports(cx: *mut JSContext, path_seg: String) -> Vec<Report> {
|
||||
let mut reports = vec![];
|
||||
|
@ -319,7 +340,7 @@ pub fn get_reports(cx: *mut JSContext, path_seg: String) -> Vec<Report> {
|
|||
unsafe {
|
||||
let rt = JS_GetRuntime(cx);
|
||||
let mut stats = ::std::mem::zeroed();
|
||||
if CollectServoSizes(rt, &mut stats) {
|
||||
if CollectServoSizes(rt, &mut stats, Some(get_size)) {
|
||||
let mut report = |mut path_suffix, kind, size| {
|
||||
let mut path = path![path_seg, "js"];
|
||||
path.append(&mut path_suffix);
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
//! a page runs its course and the script thread returns to processing events in the main event
|
||||
//! loop.
|
||||
|
||||
extern crate itertools;
|
||||
|
||||
use bluetooth_traits::BluetoothRequest;
|
||||
use canvas_traits::webgl::WebGLPipeline;
|
||||
use devtools;
|
||||
|
@ -72,8 +74,6 @@ use js::glue::GetWindowProxyClass;
|
|||
use js::jsapi::{JSAutoCompartment, JSContext, JS_SetWrapObjectCallbacks};
|
||||
use js::jsapi::{JSTracer, SetWindowProxyClass};
|
||||
use js::jsval::UndefinedValue;
|
||||
use malloc_size_of::MallocSizeOfOps;
|
||||
use mem::malloc_size_of_including_self;
|
||||
use metrics::{MAX_TASK_NS, PaintTimeMetrics};
|
||||
use microtask::{MicrotaskQueue, Microtask};
|
||||
use msg::constellation_msg::{BrowsingContextId, PipelineId, PipelineNamespace, TopLevelBrowsingContextId};
|
||||
|
@ -82,7 +82,7 @@ use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceThreads};
|
|||
use net_traits::image_cache::{ImageCache, PendingImageResponse};
|
||||
use net_traits::request::{CredentialsMode, Destination, RedirectMode, RequestInit};
|
||||
use net_traits::storage_thread::StorageType;
|
||||
use profile_traits::mem::{self, OpaqueSender, Report, ReportKind, ReportsChan};
|
||||
use profile_traits::mem::{self, OpaqueSender, ReportsChan};
|
||||
use profile_traits::time::{self, ProfilerCategory, profile};
|
||||
use script_layout_interface::message::{self, Msg, NewLayoutThreadInfo, ReflowGoal};
|
||||
use script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
|
||||
|
@ -1580,34 +1580,11 @@ impl ScriptThread {
|
|||
}
|
||||
|
||||
fn collect_reports(&self, reports_chan: ReportsChan) {
|
||||
let mut path_seg = String::from("url(");
|
||||
let mut dom_tree_size = 0;
|
||||
let documents = self.documents.borrow();
|
||||
let urls = itertools::join(documents.iter().map(|(_, d)| d.url().to_string()), ", ");
|
||||
let path_seg = format!("url({})", urls);
|
||||
|
||||
let mut reports = vec![];
|
||||
// Servo uses vanilla jemalloc, which doesn't have a
|
||||
// malloc_enclosing_size_of function.
|
||||
let mut ops = MallocSizeOfOps::new(::servo_allocator::usable_size, None, None);
|
||||
|
||||
for (_, document) in self.documents.borrow().iter() {
|
||||
let current_url = document.url();
|
||||
|
||||
for child in document.upcast::<Node>().traverse_preorder() {
|
||||
dom_tree_size += malloc_size_of_including_self(&mut ops, &*child);
|
||||
}
|
||||
dom_tree_size += malloc_size_of_including_self(&mut ops, document.window());
|
||||
|
||||
if reports.len() > 0 {
|
||||
path_seg.push_str(", ");
|
||||
}
|
||||
path_seg.push_str(current_url.as_str());
|
||||
|
||||
reports.push(Report {
|
||||
path: path![format!("url({})", current_url.as_str()), "dom-tree"],
|
||||
kind: ReportKind::ExplicitJemallocHeapSize,
|
||||
size: dom_tree_size,
|
||||
});
|
||||
}
|
||||
|
||||
path_seg.push_str(")");
|
||||
reports.extend(get_reports(self.get_cx(), path_seg));
|
||||
reports_chan.send(reports);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue