mirror of
https://github.com/servo/servo.git
synced 2025-08-23 14:25:33 +01:00
script: Measure heap usage of various ignored fields (#38791)
These changes allow using MallocSizeOf/`#[conditional_malloc_size_of]` on WebIDL callback values, and then fix a grab bag of places in the script crate that previously ignored those values. There are also some commits removing ignored fields that involved Arc/Rc that are not WebIDL callbacks, since they are now easier to support with the `#[conditional_malloc_size_of]` attribute. Testing: Manual testing on about:memory for servo.org. --------- Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
parent
604b6ea26d
commit
636e7211e0
16 changed files with 44 additions and 38 deletions
|
@ -6,6 +6,7 @@ use base::id::WebViewId;
|
|||
use constellation_traits::{ScriptToConstellationChan, ScriptToConstellationMessage};
|
||||
use embedder_traits::EmbedderMsg;
|
||||
use ipc_channel::ipc::channel;
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
|
||||
/// A trait which abstracts access to the embedder's clipboard in order to allow unit
|
||||
/// testing clipboard-dependent parts of `script`.
|
||||
|
@ -16,6 +17,7 @@ pub trait ClipboardProvider {
|
|||
fn set_text(&mut self, _: String);
|
||||
}
|
||||
|
||||
#[derive(MallocSizeOf)]
|
||||
pub(crate) struct EmbedderClipboardProvider {
|
||||
pub constellation_sender: ScriptToConstellationChan,
|
||||
pub webview_id: WebViewId,
|
||||
|
|
|
@ -823,7 +823,7 @@ pub(crate) fn create_array_buffer_with_size(
|
|||
#[cfg(feature = "webgpu")]
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
pub(crate) struct DataBlock {
|
||||
#[ignore_malloc_size_of = "Arc"]
|
||||
#[conditional_malloc_size_of]
|
||||
data: Arc<Box<[u8]>>,
|
||||
/// Data views (mutable subslices of data)
|
||||
data_views: Vec<DataView>,
|
||||
|
|
|
@ -614,28 +614,28 @@ impl CustomElementRegistryMethods<crate::DomTypeHolder> for CustomElementRegistr
|
|||
|
||||
#[derive(Clone, JSTraceable, MallocSizeOf)]
|
||||
pub(crate) struct LifecycleCallbacks {
|
||||
#[ignore_malloc_size_of = "Rc"]
|
||||
#[conditional_malloc_size_of]
|
||||
connected_callback: Option<Rc<Function>>,
|
||||
|
||||
#[ignore_malloc_size_of = "Rc"]
|
||||
#[conditional_malloc_size_of]
|
||||
disconnected_callback: Option<Rc<Function>>,
|
||||
|
||||
#[ignore_malloc_size_of = "Rc"]
|
||||
#[conditional_malloc_size_of]
|
||||
adopted_callback: Option<Rc<Function>>,
|
||||
|
||||
#[ignore_malloc_size_of = "Rc"]
|
||||
#[conditional_malloc_size_of]
|
||||
attribute_changed_callback: Option<Rc<Function>>,
|
||||
|
||||
#[ignore_malloc_size_of = "Rc"]
|
||||
#[conditional_malloc_size_of]
|
||||
form_associated_callback: Option<Rc<Function>>,
|
||||
|
||||
#[ignore_malloc_size_of = "Rc"]
|
||||
#[conditional_malloc_size_of]
|
||||
form_reset_callback: Option<Rc<Function>>,
|
||||
|
||||
#[ignore_malloc_size_of = "Rc"]
|
||||
#[conditional_malloc_size_of]
|
||||
form_disabled_callback: Option<Rc<Function>>,
|
||||
|
||||
#[ignore_malloc_size_of = "Rc"]
|
||||
#[conditional_malloc_size_of]
|
||||
form_state_restore_callback: Option<Rc<Function>>,
|
||||
}
|
||||
|
||||
|
@ -657,7 +657,7 @@ pub(crate) struct CustomElementDefinition {
|
|||
pub(crate) local_name: LocalName,
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#concept-custom-element-definition-constructor>
|
||||
#[ignore_malloc_size_of = "Rc"]
|
||||
#[conditional_malloc_size_of]
|
||||
pub(crate) constructor: Rc<CustomElementConstructor>,
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#concept-custom-element-definition-observed-attributes>
|
||||
|
@ -988,9 +988,9 @@ pub(crate) fn try_upgrade_element(element: &Element) {
|
|||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
pub(crate) enum CustomElementReaction {
|
||||
Upgrade(#[ignore_malloc_size_of = "Rc"] Rc<CustomElementDefinition>),
|
||||
Upgrade(#[conditional_malloc_size_of] Rc<CustomElementDefinition>),
|
||||
Callback(
|
||||
#[ignore_malloc_size_of = "Rc"] Rc<Function>,
|
||||
#[conditional_malloc_size_of] Rc<Function>,
|
||||
#[ignore_malloc_size_of = "mozjs"] Box<[Heap<JSVal>]>,
|
||||
),
|
||||
}
|
||||
|
|
|
@ -163,11 +163,11 @@ static CONTENT_EVENT_HANDLER_NAMES: [&str; 83] = [
|
|||
#[derive(Clone, JSTraceable, MallocSizeOf, PartialEq)]
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
pub(crate) enum CommonEventHandler {
|
||||
EventHandler(#[ignore_malloc_size_of = "Rc"] Rc<EventHandlerNonNull>),
|
||||
EventHandler(#[conditional_malloc_size_of] Rc<EventHandlerNonNull>),
|
||||
|
||||
ErrorEventHandler(#[ignore_malloc_size_of = "Rc"] Rc<OnErrorEventHandlerNonNull>),
|
||||
ErrorEventHandler(#[conditional_malloc_size_of] Rc<OnErrorEventHandlerNonNull>),
|
||||
|
||||
BeforeUnloadEventHandler(#[ignore_malloc_size_of = "Rc"] Rc<OnBeforeUnloadEventHandlerNonNull>),
|
||||
BeforeUnloadEventHandler(#[conditional_malloc_size_of] Rc<OnBeforeUnloadEventHandlerNonNull>),
|
||||
}
|
||||
|
||||
impl CommonEventHandler {
|
||||
|
@ -231,7 +231,7 @@ fn get_compiled_handler(
|
|||
|
||||
#[derive(Clone, JSTraceable, MallocSizeOf, PartialEq)]
|
||||
enum EventListenerType {
|
||||
Additive(#[ignore_malloc_size_of = "Rc"] Rc<EventListener>),
|
||||
Additive(#[conditional_malloc_size_of] Rc<EventListener>),
|
||||
Inline(RefCell<InlineEventListener>),
|
||||
}
|
||||
|
||||
|
@ -439,7 +439,7 @@ impl std::cmp::PartialEq for EventListenerEntry {
|
|||
#[derive(Clone, JSTraceable, MallocSizeOf)]
|
||||
/// A mix of potentially uncompiled and compiled event listeners of the same type.
|
||||
pub(crate) struct EventListeners(
|
||||
#[ignore_malloc_size_of = "Rc"] Vec<Rc<RefCell<EventListenerEntry>>>,
|
||||
#[conditional_malloc_size_of] Vec<Rc<RefCell<EventListenerEntry>>>,
|
||||
);
|
||||
|
||||
impl Deref for EventListeners {
|
||||
|
|
|
@ -361,7 +361,6 @@ pub(crate) struct HTMLInputElement {
|
|||
size: Cell<u32>,
|
||||
maxlength: Cell<i32>,
|
||||
minlength: Cell<i32>,
|
||||
#[ignore_malloc_size_of = "TextInput contains an IPCSender which cannot be measured"]
|
||||
#[no_trace]
|
||||
textinput: DomRefCell<TextInput<EmbedderClipboardProvider>>,
|
||||
// https://html.spec.whatwg.org/multipage/#concept-input-value-dirty-flag
|
||||
|
|
|
@ -111,13 +111,17 @@ static MEDIA_CONTROL_CSS: &str = include_str!("../resources/media-controls.css")
|
|||
/// A JS file to control the media controls.
|
||||
static MEDIA_CONTROL_JS: &str = include_str!("../resources/media-controls.js");
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(MallocSizeOf, PartialEq)]
|
||||
enum FrameStatus {
|
||||
Locked,
|
||||
Unlocked,
|
||||
}
|
||||
|
||||
struct FrameHolder(FrameStatus, VideoFrame);
|
||||
#[derive(MallocSizeOf)]
|
||||
struct FrameHolder(
|
||||
FrameStatus,
|
||||
#[ignore_malloc_size_of = "defined in servo-media"] VideoFrame,
|
||||
);
|
||||
|
||||
impl FrameHolder {
|
||||
fn new(frame: VideoFrame) -> FrameHolder {
|
||||
|
@ -159,6 +163,7 @@ impl FrameHolder {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(MallocSizeOf)]
|
||||
pub(crate) struct MediaFrameRenderer {
|
||||
player_id: Option<u64>,
|
||||
compositor_api: CrossProcessCompositorApi,
|
||||
|
@ -389,7 +394,7 @@ pub(crate) struct HTMLMediaElement {
|
|||
#[ignore_malloc_size_of = "servo_media"]
|
||||
#[no_trace]
|
||||
player: DomRefCell<Option<Arc<Mutex<dyn Player>>>>,
|
||||
#[ignore_malloc_size_of = "Arc"]
|
||||
#[conditional_malloc_size_of]
|
||||
#[no_trace]
|
||||
video_renderer: Arc<Mutex<MediaFrameRenderer>>,
|
||||
#[ignore_malloc_size_of = "Arc"]
|
||||
|
@ -417,7 +422,6 @@ pub(crate) struct HTMLMediaElement {
|
|||
#[no_trace]
|
||||
blob_url: DomRefCell<Option<ServoUrl>>,
|
||||
/// <https://html.spec.whatwg.org/multipage/#dom-media-played>
|
||||
#[ignore_malloc_size_of = "Rc"]
|
||||
played: DomRefCell<TimeRangesContainer>,
|
||||
// https://html.spec.whatwg.org/multipage/#dom-media-audiotracks
|
||||
audio_tracks_list: MutNullableDom<AudioTrackList>,
|
||||
|
|
|
@ -50,7 +50,6 @@ use crate::textinput::{
|
|||
#[dom_struct]
|
||||
pub(crate) struct HTMLTextAreaElement {
|
||||
htmlelement: HTMLElement,
|
||||
#[ignore_malloc_size_of = "TextInput contains an IPCSender which cannot be measured"]
|
||||
#[no_trace]
|
||||
textinput: DomRefCell<TextInput<EmbedderClipboardProvider>>,
|
||||
placeholder: DomRefCell<DOMString>,
|
||||
|
|
|
@ -66,7 +66,7 @@ pub(crate) struct ElementRareData {
|
|||
/// <https://html.spec.whatwg.org/multipage/#custom-element-reaction-queue>
|
||||
pub(crate) custom_element_reaction_queue: Vec<CustomElementReaction>,
|
||||
/// <https://dom.spec.whatwg.org/#concept-element-custom-element-definition>
|
||||
#[ignore_malloc_size_of = "Rc"]
|
||||
#[conditional_malloc_size_of]
|
||||
pub(crate) custom_element_definition: Option<Rc<CustomElementDefinition>>,
|
||||
/// <https://dom.spec.whatwg.org/#concept-element-custom-element-state>
|
||||
pub(crate) custom_element_state: CustomElementState,
|
||||
|
|
|
@ -115,17 +115,18 @@ impl Callback for StartAlgorithmRejectionHandler {
|
|||
}
|
||||
|
||||
/// <https://streams.spec.whatwg.org/#value-with-size>
|
||||
#[derive(Debug, JSTraceable, PartialEq)]
|
||||
#[derive(Debug, JSTraceable, MallocSizeOf, PartialEq)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
pub(crate) struct ValueWithSize {
|
||||
/// <https://streams.spec.whatwg.org/#value-with-size-value>
|
||||
#[ignore_malloc_size_of = "Heap is measured by mozjs"]
|
||||
pub(crate) value: Box<Heap<JSVal>>,
|
||||
/// <https://streams.spec.whatwg.org/#value-with-size-size>
|
||||
pub(crate) size: f64,
|
||||
}
|
||||
|
||||
/// <https://streams.spec.whatwg.org/#value-with-size>
|
||||
#[derive(Debug, JSTraceable, PartialEq)]
|
||||
#[derive(Debug, JSTraceable, MallocSizeOf, PartialEq)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
pub(crate) enum EnqueuedValue {
|
||||
/// A value enqueued from Rust.
|
||||
|
@ -191,7 +192,6 @@ fn is_non_negative_number(value: &EnqueuedValue) -> bool {
|
|||
#[derive(Default, JSTraceable, MallocSizeOf)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
pub(crate) struct QueueWithSizes {
|
||||
#[ignore_malloc_size_of = "EnqueuedValue::Js"]
|
||||
queue: VecDeque<EnqueuedValue>,
|
||||
/// <https://streams.spec.whatwg.org/#readablestreamdefaultcontroller-queuetotalsize>
|
||||
pub(crate) total_size: f64,
|
||||
|
|
|
@ -55,7 +55,7 @@ pub(crate) trait MicrotaskRunnable {
|
|||
/// A promise callback scheduled to run during the next microtask checkpoint (#4283).
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
pub(crate) struct EnqueuedPromiseCallback {
|
||||
#[ignore_malloc_size_of = "Rc has unclear ownership"]
|
||||
#[conditional_malloc_size_of]
|
||||
pub(crate) callback: Rc<PromiseJobCallback>,
|
||||
#[no_trace]
|
||||
pub(crate) pipeline: PipelineId,
|
||||
|
@ -66,7 +66,7 @@ pub(crate) struct EnqueuedPromiseCallback {
|
|||
/// identical to EnqueuedPromiseCallback once it's on the queue
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
pub(crate) struct UserMicrotask {
|
||||
#[ignore_malloc_size_of = "Rc has unclear ownership"]
|
||||
#[conditional_malloc_size_of]
|
||||
pub(crate) callback: Rc<VoidFunction>,
|
||||
#[no_trace]
|
||||
pub(crate) pipeline: PipelineId,
|
||||
|
|
|
@ -118,7 +118,7 @@ impl fmt::Debug for dyn TaskBox {
|
|||
/// Encapsulated state required to create cancellable tasks from non-script threads.
|
||||
#[derive(Clone, Default, JSTraceable, MallocSizeOf)]
|
||||
pub(crate) struct TaskCanceller {
|
||||
#[ignore_malloc_size_of = "This is difficult, because only one of them should be measured"]
|
||||
#[conditional_malloc_size_of]
|
||||
pub(crate) cancelled: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
|
|
|
@ -381,7 +381,6 @@ struct JsTimerEntry {
|
|||
// TODO: Handle rooting during invocation when movable GC is turned on
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
pub(crate) struct JsTimerTask {
|
||||
#[ignore_malloc_size_of = "Because it is non-owning"]
|
||||
handle: JsTimerHandle,
|
||||
#[no_trace]
|
||||
source: TimerSource,
|
||||
|
@ -409,7 +408,7 @@ pub(crate) enum TimerCallback {
|
|||
enum InternalTimerCallback {
|
||||
StringTimerCallback(DOMString),
|
||||
FunctionTimerCallback(
|
||||
#[ignore_malloc_size_of = "Rc"] Rc<Function>,
|
||||
#[conditional_malloc_size_of] Rc<Function>,
|
||||
#[ignore_malloc_size_of = "Rc"] Rc<Box<[Heap<JSVal>]>>,
|
||||
),
|
||||
}
|
||||
|
|
|
@ -55,11 +55,13 @@ pub enum ExceptionHandling {
|
|||
|
||||
/// A common base class for representing IDL callback function and
|
||||
/// callback interface types.
|
||||
#[derive(JSTraceable)]
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
pub struct CallbackObject<D: DomTypes> {
|
||||
/// The underlying `JSObject`.
|
||||
#[ignore_malloc_size_of = "measured by mozjs"]
|
||||
callback: Heap<*mut JSObject>,
|
||||
#[ignore_malloc_size_of = "measured by mozjs"]
|
||||
permanent_js_root: Heap<JSVal>,
|
||||
|
||||
/// The ["callback context"], that is, the global to use as incumbent
|
||||
|
@ -147,7 +149,7 @@ pub trait CallbackContainer<D: DomTypes> {
|
|||
}
|
||||
|
||||
/// A common base class for representing IDL callback function types.
|
||||
#[derive(JSTraceable, PartialEq)]
|
||||
#[derive(JSTraceable, MallocSizeOf, PartialEq)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
pub struct CallbackFunction<D: DomTypes> {
|
||||
object: CallbackObject<D>,
|
||||
|
@ -180,7 +182,7 @@ impl<D: DomTypes> CallbackFunction<D> {
|
|||
}
|
||||
|
||||
/// A common base class for representing IDL callback interface types.
|
||||
#[derive(JSTraceable, PartialEq)]
|
||||
#[derive(JSTraceable, MallocSizeOf, PartialEq)]
|
||||
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
||||
pub struct CallbackInterface<D: DomTypes> {
|
||||
object: CallbackObject<D>,
|
||||
|
|
|
@ -8057,7 +8057,7 @@ class CGCallback(CGClass):
|
|||
constructors=self.getConstructors(),
|
||||
methods=realMethods,
|
||||
templateSpecialization=['D: DomTypes'],
|
||||
decorators="#[derive(JSTraceable, PartialEq)]\n"
|
||||
decorators="#[derive(JSTraceable, MallocSizeOf, PartialEq)]\n"
|
||||
"#[cfg_attr(crown, allow(crown::unrooted_must_root))]\n"
|
||||
"#[cfg_attr(crown, crown::unrooted_must_root_lint::allow_unrooted_interior)]")
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ use euclid::default::Size2D as UntypedSize2D;
|
|||
use http::{HeaderMap, Method};
|
||||
use ipc_channel::Error as IpcError;
|
||||
use ipc_channel::ipc::{IpcReceiver, IpcSender};
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use net_traits::policy_container::PolicyContainer;
|
||||
use net_traits::request::{Destination, InsecureRequestsPolicy, Referrer, RequestBody};
|
||||
use net_traits::storage_thread::StorageType;
|
||||
|
@ -42,7 +43,7 @@ use crate::{
|
|||
};
|
||||
|
||||
/// A Script to Constellation channel.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||
pub struct ScriptToConstellationChan {
|
||||
/// Sender for communicating with constellation thread.
|
||||
pub sender: IpcSender<(PipelineId, ScriptToConstellationMessage)>,
|
||||
|
|
|
@ -175,7 +175,7 @@ pub struct PendingRasterizationImage {
|
|||
pub size: DeviceIntSize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy, Debug, MallocSizeOf)]
|
||||
pub struct MediaFrame {
|
||||
pub image_key: webrender_api::ImageKey,
|
||||
pub width: i32,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue