From 5c7ea4bdeebbdcc7c8406c3219c6b210873117c6 Mon Sep 17 00:00:00 2001 From: Narfinger Date: Wed, 3 Sep 2025 20:15:19 +0200 Subject: [PATCH] constellation: Use `FnvHashMap` for hashmaps that use ids as keys (#39106) FNV is faster for hashing less than 16 bytes of data and the cryptographic properties of the default HashMap are not needed for the various ids. Testing: This does not change functionality. Signed-off-by: Narfinger --- Cargo.lock | 4 ++ components/compositing/compositor.rs | 3 +- components/constellation/Cargo.toml | 1 + components/constellation/broadcastchannel.rs | 3 +- components/constellation/browsingcontext.rs | 15 +++--- components/constellation/constellation.rs | 47 ++++++++++--------- .../constellation/constellation_webview.rs | 9 ++-- components/constellation/webview_manager.rs | 3 +- components/layout/layout_impl.rs | 3 +- components/script/dom/globalscope.rs | 3 +- components/script/script_thread.rs | 3 +- components/shared/compositing/Cargo.toml | 1 + components/shared/compositing/display_list.rs | 8 +++- components/shared/constellation/Cargo.toml | 1 + .../constellation/from_script_message.rs | 4 +- components/shared/constellation/lib.rs | 9 ++-- components/shared/layout/lib.rs | 3 +- components/shared/script/Cargo.toml | 1 + components/shared/script/lib.rs | 4 +- 19 files changed, 71 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 30c721e36a7..8264aa48ef8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1500,6 +1500,7 @@ dependencies = [ "dpi", "embedder_traits", "euclid", + "fnv", "gleam", "glow", "image", @@ -1563,6 +1564,7 @@ dependencies = [ "devtools_traits", "embedder_traits", "euclid", + "fnv", "fonts", "gaol", "ipc-channel", @@ -1601,6 +1603,7 @@ dependencies = [ "devtools_traits", "embedder_traits", "euclid", + "fnv", "fonts_traits", "http 1.3.1", "hyper_serde", @@ -7459,6 +7462,7 @@ dependencies = [ "devtools_traits", "embedder_traits", "euclid", + "fnv", "ipc-channel", "keyboard-types", "log", diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 87b04af91be..e4349b40b0d 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -28,6 +28,7 @@ use crossbeam_channel::Sender; use dpi::PhysicalSize; use embedder_traits::{CompositorHitTestResult, InputEvent, ShutdownState, ViewportDetails}; use euclid::{Point2D, Rect, Scale, Size2D, Transform3D}; +use fnv::FnvHashMap; use ipc_channel::ipc::{self, IpcSharedMemory}; use log::{debug, info, trace, warn}; use pixels::{CorsStatus, ImageFrame, ImageMetadata, PixelFormat, RasterImage}; @@ -1183,7 +1184,7 @@ impl IOCompositor { // complete (i.e. has *all* layers painted to the requested epoch). // This gets sent to the constellation for comparison with the current // frame tree. - let mut pipeline_epochs = HashMap::new(); + let mut pipeline_epochs = FnvHashMap::default(); for id in self .webview_renderers .iter() diff --git a/components/constellation/Cargo.toml b/components/constellation/Cargo.toml index 5aaebc3c004..28a64d8bbc9 100644 --- a/components/constellation/Cargo.toml +++ b/components/constellation/Cargo.toml @@ -38,6 +38,7 @@ devtools_traits = { workspace = true } embedder_traits = { workspace = true } euclid = { workspace = true } fonts = { path = "../fonts" } +fnv = { workspace = true } ipc-channel = { workspace = true } keyboard-types = { workspace = true } layout_api = { workspace = true } diff --git a/components/constellation/broadcastchannel.rs b/components/constellation/broadcastchannel.rs index 95dacbeb9ab..d76536c4749 100644 --- a/components/constellation/broadcastchannel.rs +++ b/components/constellation/broadcastchannel.rs @@ -6,6 +6,7 @@ use std::collections::HashMap; use base::id::BroadcastChannelRouterId; use constellation_traits::BroadcastChannelMsg; +use fnv::FnvHashMap; use ipc_channel::ipc::IpcSender; use log::warn; use servo_url::ImmutableOrigin; @@ -13,7 +14,7 @@ use servo_url::ImmutableOrigin; #[derive(Default)] pub(crate) struct BroadcastChannels { /// A map of broadcast routers to their IPC sender. - routers: HashMap>, + routers: FnvHashMap>, /// A map of origin to a map of channel name to a list of relevant routers. channels: HashMap>>, diff --git a/components/constellation/browsingcontext.rs b/components/constellation/browsingcontext.rs index 0a6974a1f2a..9a99fe21ab9 100644 --- a/components/constellation/browsingcontext.rs +++ b/components/constellation/browsingcontext.rs @@ -2,10 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::collections::{HashMap, HashSet}; - use base::id::{BrowsingContextGroupId, BrowsingContextId, PipelineId, WebViewId}; use embedder_traits::ViewportDetails; +use fnv::{FnvHashMap, FnvHashSet}; use log::warn; use crate::pipeline::Pipeline; @@ -71,7 +70,7 @@ pub struct BrowsingContext { /// All the pipelines that have been presented or will be presented in /// this browsing context. - pub pipelines: HashSet, + pub pipelines: FnvHashSet, } impl BrowsingContext { @@ -89,7 +88,7 @@ impl BrowsingContext { inherited_secure_context: Option, throttled: bool, ) -> BrowsingContext { - let mut pipelines = HashSet::new(); + let mut pipelines = FnvHashSet::default(); pipelines.insert(pipeline_id); BrowsingContext { bc_group_id, @@ -123,12 +122,12 @@ pub struct FullyActiveBrowsingContextsIterator<'a> { pub stack: Vec, /// The set of all browsing contexts. - pub browsing_contexts: &'a HashMap, + pub browsing_contexts: &'a FnvHashMap, /// The set of all pipelines. We use this to find the active /// children of a frame, which are the iframes in the currently /// active document. - pub pipelines: &'a HashMap, + pub pipelines: &'a FnvHashMap, } impl<'a> Iterator for FullyActiveBrowsingContextsIterator<'a> { @@ -170,12 +169,12 @@ pub struct AllBrowsingContextsIterator<'a> { pub stack: Vec, /// The set of all browsing contexts. - pub browsing_contexts: &'a HashMap, + pub browsing_contexts: &'a FnvHashMap, /// The set of all pipelines. We use this to find the /// children of a browsing context, which are the iframes in all documents /// in the session history. - pub pipelines: &'a HashMap, + pub pipelines: &'a FnvHashMap, } impl<'a> Iterator for AllBrowsingContextsIterator<'a> { diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 15afd57a217..351a2f42b01 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -139,6 +139,7 @@ use embedder_traits::{ }; use euclid::Size2D; use euclid::default::Size2D as UntypedSize2D; +use fnv::{FnvHashMap, FnvHashSet}; use fonts::SystemFontServiceProxy; use ipc_channel::Error as IpcError; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; @@ -240,7 +241,7 @@ struct WebrenderWGPU { #[derive(Clone, Default)] struct BrowsingContextGroup { /// A browsing context group holds a set of top-level browsing contexts. - top_level_browsing_context_set: HashSet, + top_level_browsing_context_set: FnvHashSet, /// The set of all event loops in this BrowsingContextGroup. /// We store the event loops in a map @@ -384,25 +385,25 @@ pub struct Constellation { webrender_wgpu: WebrenderWGPU, /// A map of message-port Id to info. - message_ports: HashMap, + message_ports: FnvHashMap, /// A map of router-id to ipc-sender, to route messages to ports. - message_port_routers: HashMap>, + message_port_routers: FnvHashMap>, /// Bookkeeping for BroadcastChannel functionnality. broadcast_channels: BroadcastChannels, /// The set of all the pipelines in the browser. (See the `pipeline` module /// for more details.) - pipelines: HashMap, + pipelines: FnvHashMap, /// The set of all the browsing contexts in the browser. - browsing_contexts: HashMap, + browsing_contexts: FnvHashMap, /// A user agent holds a a set of browsing context groups. /// /// - browsing_context_group_set: HashMap, + browsing_context_group_set: FnvHashMap, /// The Id counter for BrowsingContextGroup. browsing_context_group_next_id: u32, @@ -425,7 +426,7 @@ pub struct Constellation { webdriver_input_command_reponse_sender: Option>, /// Document states for loaded pipelines (used only when writing screenshots). - document_states: HashMap, + document_states: FnvHashMap, /// Are we shutting down? shutting_down: bool, @@ -481,7 +482,7 @@ pub struct Constellation { async_runtime: Box, /// When in single-process mode, join handles for script-threads. - script_join_handles: HashMap>, + script_join_handles: FnvHashMap>, /// A list of URLs that can access privileged internal APIs. privileged_urls: Vec, @@ -696,11 +697,11 @@ where swmanager_ipc_sender, browsing_context_group_set: Default::default(), browsing_context_group_next_id: Default::default(), - message_ports: HashMap::new(), - message_port_routers: HashMap::new(), + message_ports: Default::default(), + message_port_routers: Default::default(), broadcast_channels: Default::default(), - pipelines: HashMap::new(), - browsing_contexts: HashMap::new(), + pipelines: Default::default(), + browsing_contexts: Default::default(), pending_changes: vec![], // We initialize the namespace at 2, since we reserved // namespace 0 for the embedder, and 0 for the constellation @@ -710,7 +711,7 @@ where phantom: PhantomData, webdriver_load_status_sender: None, webdriver_input_command_reponse_sender: None, - document_states: HashMap::new(), + document_states: Default::default(), #[cfg(feature = "webgpu")] webrender_wgpu, shutting_down: false, @@ -725,7 +726,7 @@ where webgl_threads: state.webgl_threads, webxr_registry: state.webxr_registry, canvas: OnceCell::new(), - pending_approval_navigations: HashMap::new(), + pending_approval_navigations: Default::default(), pressed_mouse_buttons: 0, active_keyboard_modifiers: Modifiers::empty(), hard_fail, @@ -2119,7 +2120,7 @@ where fn handle_message_port_transfer_failed( &mut self, - ports: HashMap, + ports: FnvHashMap, ) { for (port_id, mut transfer_info) in ports.into_iter() { let entry = match self.message_ports.remove(&port_id) { @@ -2201,7 +2202,7 @@ where router_id: MessagePortRouterId, ports: Vec, ) { - let mut response = HashMap::new(); + let mut response = FnvHashMap::default(); for port_id in ports.into_iter() { let entry = match self.message_ports.remove(&port_id) { None => { @@ -3784,9 +3785,11 @@ where webview_id: WebViewId, direction: TraversalDirection, ) { - let mut browsing_context_changes = HashMap::::new(); - let mut pipeline_changes = HashMap::, ServoUrl)>::new(); - let mut url_to_load = HashMap::::new(); + let mut browsing_context_changes = + FnvHashMap::::default(); + let mut pipeline_changes = + FnvHashMap::, ServoUrl)>::default(); + let mut url_to_load = FnvHashMap::::default(); { let session_history = self.get_joint_session_history(webview_id); match direction { @@ -4792,7 +4795,7 @@ where }; let mut pipelines_to_close = vec![]; - let mut states_to_close = HashMap::new(); + let mut states_to_close = FnvHashMap::default(); let diffs_to_close = self .get_joint_session_history(change.webview_id) @@ -5049,7 +5052,7 @@ where #[servo_tracing::instrument(skip_all)] fn handle_is_ready_to_save_image( &mut self, - pipeline_states: HashMap, + pipeline_states: FnvHashMap, ) -> ReadyToSave { // Note that this function can panic, due to ipc-channel creation // failure. Avoiding this panic would require a mechanism for dealing @@ -5593,7 +5596,7 @@ where fn handle_set_scroll_states( &self, pipeline_id: PipelineId, - scroll_states: HashMap, + scroll_states: FnvHashMap, ) { let Some(pipeline) = self.pipelines.get(&pipeline_id) else { warn!("Discarding scroll offset update for unknown pipeline"); diff --git a/components/constellation/constellation_webview.rs b/components/constellation/constellation_webview.rs index f2264ace8cb..3aa0b15678c 100644 --- a/components/constellation/constellation_webview.rs +++ b/components/constellation/constellation_webview.rs @@ -2,11 +2,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use std::collections::HashMap; - use base::id::{BrowsingContextId, PipelineId}; use embedder_traits::{InputEvent, MouseLeftViewportEvent, Theme}; use euclid::Point2D; +use fnv::FnvHashMap; use log::warn; use script_traits::{ConstellationInputEvent, ScriptThreadMessage}; use style_traits::CSSPixel; @@ -64,7 +63,7 @@ impl ConstellationWebView { fn target_pipeline_id_for_input_event( &self, event: &ConstellationInputEvent, - browsing_contexts: &HashMap, + browsing_contexts: &FnvHashMap, ) -> Option { if let Some(hit_test_result) = &event.hit_test_result { return Some(hit_test_result.pipeline_id); @@ -85,8 +84,8 @@ impl ConstellationWebView { pub(crate) fn forward_input_event( &mut self, event: ConstellationInputEvent, - pipelines: &HashMap, - browsing_contexts: &HashMap, + pipelines: &FnvHashMap, + browsing_contexts: &FnvHashMap, ) { let Some(pipeline_id) = self.target_pipeline_id_for_input_event(&event, browsing_contexts) else { diff --git a/components/constellation/webview_manager.rs b/components/constellation/webview_manager.rs index e28e54d59a8..df9a9cd9afb 100644 --- a/components/constellation/webview_manager.rs +++ b/components/constellation/webview_manager.rs @@ -5,12 +5,13 @@ use std::collections::HashMap; use base::id::WebViewId; +use fnv::FnvHashMap; #[derive(Debug)] pub struct WebViewManager { /// Our top-level browsing contexts. In the WebRender scene, their pipelines are the children of /// a single root pipeline that also applies any pinch zoom transformation. - webviews: HashMap, + webviews: FnvHashMap, /// The order in which they were focused, latest last. focus_order: Vec, diff --git a/components/layout/layout_impl.rs b/components/layout/layout_impl.rs index 6985a6d4a42..92bf50cb39c 100644 --- a/components/layout/layout_impl.rs +++ b/components/layout/layout_impl.rs @@ -5,7 +5,6 @@ #![allow(unsafe_code)] use std::cell::{Cell, RefCell}; -use std::collections::HashMap; use std::fmt::Debug; use std::process; use std::rc::Rc; @@ -503,7 +502,7 @@ impl Layout for LayoutThread { fn set_scroll_offsets_from_renderer( &mut self, - scroll_states: &HashMap, + scroll_states: &FnvHashMap, ) { let mut stacking_context_tree = self.stacking_context_tree.borrow_mut(); let Some(stacking_context_tree) = stacking_context_tree.as_mut() else { diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 39a85a654ff..e4c3842385a 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -27,6 +27,7 @@ use crossbeam_channel::Sender; use devtools_traits::{PageError, ScriptToDevtoolsControlMsg}; use dom_struct::dom_struct; use embedder_traits::{EmbedderMsg, JavaScriptEvaluationError, ScriptToEmbedderChan}; +use fnv::FnvHashMap; use fonts::FontContext; use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::router::ROUTER; @@ -561,7 +562,7 @@ impl MessageListener { }; let mut succeeded = vec![]; - let mut failed = HashMap::new(); + let mut failed = FnvHashMap::default(); for (id, info) in ports.into_iter() { if global.is_managing_port(&id) { diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index ef257477bb4..0858fa99d9d 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -55,6 +55,7 @@ use embedder_traits::{ }; use euclid::Point2D; use euclid::default::Rect; +use fnv::FnvHashMap; use fonts::{FontContext, SystemFontServiceProxy}; use headers::{HeaderMapExt, LastModified, ReferrerPolicy as ReferrerPolicyHeader}; use http::header::REFRESH; @@ -1943,7 +1944,7 @@ impl ScriptThread { fn handle_set_scroll_states( &self, pipeline_id: PipelineId, - scroll_states: HashMap, + scroll_states: FnvHashMap, ) { let Some(window) = self.documents.borrow().find_window(pipeline_id) else { warn!("Received scroll states for closed pipeline {pipeline_id}"); diff --git a/components/shared/compositing/Cargo.toml b/components/shared/compositing/Cargo.toml index 11ac6223766..f30e71524ab 100644 --- a/components/shared/compositing/Cargo.toml +++ b/components/shared/compositing/Cargo.toml @@ -22,6 +22,7 @@ crossbeam-channel = { workspace = true } dpi = { version = "0.1" } embedder_traits = { workspace = true } euclid = { workspace = true } +fnv = { workspace = true } gleam = { workspace = true } glow = { workspace = true } image = { workspace = true } diff --git a/components/shared/compositing/display_list.rs b/components/shared/compositing/display_list.rs index 979bbdf84cb..431b1b1eff2 100644 --- a/components/shared/compositing/display_list.rs +++ b/components/shared/compositing/display_list.rs @@ -12,6 +12,7 @@ use base::print_tree::PrintTree; use bitflags::bitflags; use embedder_traits::ViewportDetails; use euclid::SideOffsets2D; +use fnv::FnvHashMap; use malloc_size_of_derive::MallocSizeOf; use serde::{Deserialize, Serialize}; use servo_geometry::FastLayoutTransform; @@ -558,7 +559,10 @@ impl ScrollTree { /// Given a set of all scroll offsets coming from the Servo renderer, update all of the offsets /// for nodes that actually exist in this tree. - pub fn set_all_scroll_offsets(&mut self, offsets: &HashMap) { + pub fn set_all_scroll_offsets( + &mut self, + offsets: &FnvHashMap, + ) { for node in self.nodes.iter_mut() { if let SpatialTreeNodeInfo::Scroll(ref mut scroll_info) = node.info { if let Some(offset) = offsets.get(&scroll_info.external_id) { @@ -583,7 +587,7 @@ impl ScrollTree { /// Collect all of the scroll offsets of the scrolling nodes of this tree into a /// [`HashMap`] which can be applied to another tree. - pub fn scroll_offsets(&self) -> HashMap { + pub fn scroll_offsets(&self) -> FnvHashMap { HashMap::from_iter(self.nodes.iter().filter_map(|node| match node.info { SpatialTreeNodeInfo::Scroll(ref scroll_info) => { Some((scroll_info.external_id, scroll_info.offset)) diff --git a/components/shared/constellation/Cargo.toml b/components/shared/constellation/Cargo.toml index beee88ba3c4..63874814f24 100644 --- a/components/shared/constellation/Cargo.toml +++ b/components/shared/constellation/Cargo.toml @@ -23,6 +23,7 @@ devtools_traits = { workspace = true } embedder_traits = { workspace = true } euclid = { workspace = true } fonts_traits = { workspace = true } +fnv = { workspace = true } http = { workspace = true } hyper_serde = { workspace = true } ipc-channel = { workspace = true } diff --git a/components/shared/constellation/from_script_message.rs b/components/shared/constellation/from_script_message.rs index ff80c761b0d..7b5d2e79fdd 100644 --- a/components/shared/constellation/from_script_message.rs +++ b/components/shared/constellation/from_script_message.rs @@ -4,7 +4,6 @@ //! Messages send from the ScriptThread to the Constellation. -use std::collections::HashMap; use std::fmt; use base::Epoch; @@ -22,6 +21,7 @@ use embedder_traits::{ ViewportDetails, WebDriverMessageId, }; use euclid::default::Size2D as UntypedSize2D; +use fnv::FnvHashMap; use fonts_traits::SystemFontServiceProxySender; use http::{HeaderMap, Method}; use ipc_channel::ipc::IpcSender; @@ -492,7 +492,7 @@ pub enum ScriptToConstellationMessage { /* The ids of ports transferred successfully */ Vec, /* The ids, and buffers, of ports whose transfer failed */ - HashMap, + FnvHashMap, ), /// A new message-port was created or transferred, with corresponding control-sender. NewMessagePort(MessagePortRouterId, MessagePortId), diff --git a/components/shared/constellation/lib.rs b/components/shared/constellation/lib.rs index f4673d841e2..55ab09795b8 100644 --- a/components/shared/constellation/lib.rs +++ b/components/shared/constellation/lib.rs @@ -11,7 +11,7 @@ mod from_script_message; mod structured_data; -use std::collections::{HashMap, VecDeque}; +use std::collections::VecDeque; use std::fmt; use std::time::Duration; @@ -22,6 +22,7 @@ use embedder_traits::{ CompositorHitTestResult, FocusId, InputEvent, JavaScriptEvaluationId, MediaSessionActionType, Theme, TraversalId, ViewportDetails, WebDriverCommandMsg, WebDriverCommandResponse, }; +use fnv::FnvHashMap; pub use from_script_message::*; use ipc_channel::ipc::IpcSender; use malloc_size_of_derive::MallocSizeOf; @@ -41,7 +42,7 @@ pub enum EmbedderToConstellationMessage { /// Exit the constellation. Exit, /// Query the constellation to see if the current compositor output is stable - IsReadyToSaveImage(HashMap), + IsReadyToSaveImage(FnvHashMap), /// Whether to allow script to navigate. AllowNavigationResponse(PipelineId, bool), /// Request to load a page. @@ -94,7 +95,7 @@ pub enum EmbedderToConstellationMessage { SetWebViewThrottled(WebViewId, bool), /// The Servo renderer scrolled and is updating the scroll states of the nodes in the /// given pipeline via the constellation. - SetScrollStates(PipelineId, HashMap), + SetScrollStates(PipelineId, FnvHashMap), /// Notify the constellation that a particular paint metric event has happened for the given pipeline. PaintMetric(PipelineId, PaintMetricEvent), /// Evaluate a JavaScript string in the context of a `WebView`. When execution is complete or an @@ -180,7 +181,7 @@ pub struct PortTransferInfo { #[allow(clippy::large_enum_variant)] pub enum MessagePortMsg { /// Complete the transfer for a batch of ports. - CompleteTransfer(HashMap), + CompleteTransfer(FnvHashMap), /// Complete the transfer of a single port, /// whose transfer was pending because it had been requested /// while a previous failed transfer was being rolled-back. diff --git a/components/shared/layout/lib.rs b/components/shared/layout/lib.rs index 0f279bcb1c1..eb91c1657ce 100644 --- a/components/shared/layout/lib.rs +++ b/components/shared/layout/lib.rs @@ -12,7 +12,6 @@ mod layout_damage; pub mod wrapper_traits; use std::any::Any; -use std::collections::HashMap; use std::sync::Arc; use std::sync::atomic::{AtomicIsize, AtomicU64, Ordering}; use std::thread::JoinHandle; @@ -281,7 +280,7 @@ pub trait Layout { /// Set the scroll states of this layout after a compositor scroll. fn set_scroll_offsets_from_renderer( &mut self, - scroll_states: &HashMap, + scroll_states: &FnvHashMap, ); /// Get the scroll offset of the given scroll node with id of [`ExternalScrollId`] or `None` if it does diff --git a/components/shared/script/Cargo.toml b/components/shared/script/Cargo.toml index ca5433e4445..88ba0891a25 100644 --- a/components/shared/script/Cargo.toml +++ b/components/shared/script/Cargo.toml @@ -26,6 +26,7 @@ crossbeam-channel = { workspace = true } devtools_traits = { workspace = true } embedder_traits = { workspace = true } euclid = { workspace = true } +fnv = { workspace = true } ipc-channel = { workspace = true } keyboard-types = { workspace = true } malloc_size_of = { workspace = true } diff --git a/components/shared/script/lib.rs b/components/shared/script/lib.rs index e16f835c47e..90fbae09b74 100644 --- a/components/shared/script/lib.rs +++ b/components/shared/script/lib.rs @@ -9,7 +9,6 @@ #![deny(missing_docs)] #![deny(unsafe_code)] -use std::collections::HashMap; use std::fmt; use std::sync::Arc; @@ -33,6 +32,7 @@ use embedder_traits::{ MediaSessionActionType, ScriptToEmbedderChan, Theme, ViewportDetails, WebDriverScriptCommand, }; use euclid::{Rect, Scale, Size2D, UnknownUnit}; +use fnv::FnvHashMap; use ipc_channel::ipc::{IpcReceiver, IpcSender}; use keyboard_types::Modifiers; use malloc_size_of_derive::MallocSizeOf; @@ -253,7 +253,7 @@ pub enum ScriptThreadMessage { SetWebGPUPort(IpcReceiver), /// The compositor scrolled and is updating the scroll states of the nodes in the given /// pipeline via the Constellation. - SetScrollStates(PipelineId, HashMap), + SetScrollStates(PipelineId, FnvHashMap), /// Evaluate the given JavaScript and return a result via a corresponding message /// to the Constellation. EvaluateJavaScript(PipelineId, JavaScriptEvaluationId, String),