diff --git a/Cargo.lock b/Cargo.lock index a1b070f90f754..fff9ca5566766 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4394,6 +4394,7 @@ dependencies = [ "next-core", "petgraph", "regex", + "rustc-hash 2.1.0", "serde", "serde_json", "shadow-rs", @@ -9082,6 +9083,7 @@ dependencies = [ "lsp-server", "lsp-types", "proc-macro2", + "rustc-hash 2.1.0", "serde", "serde_json", "serde_path_to_error", @@ -9176,6 +9178,7 @@ dependencies = [ "cargo-lock", "glob", "quote", + "rustc-hash 2.1.0", "syn 1.0.109", "turbo-tasks-macros-shared", ] @@ -9248,6 +9251,7 @@ dependencies = [ "parking_lot", "rayon", "rstest", + "rustc-hash 2.1.0", "serde", "serde_bytes", "serde_json", @@ -9283,6 +9287,7 @@ dependencies = [ "proc-macro2", "quote", "regex", + "rustc-hash 2.1.0", "syn 1.0.109", "turbo-tasks-macros-shared", ] @@ -9418,6 +9423,7 @@ dependencies = [ "portpicker", "rand", "regex", + "rustc-hash 2.1.0", "serde_json", "tempfile", "tokio", @@ -9465,6 +9471,7 @@ dependencies = [ "mime", "owo-colors 3.5.0", "regex", + "rustc-hash 2.1.0", "serde", "tokio", "tracing", @@ -9501,6 +9508,7 @@ dependencies = [ "clap", "crossterm 0.26.1", "owo-colors 3.5.0", + "rustc-hash 2.1.0", "serde", "turbo-tasks", "turbo-tasks-build", @@ -9569,6 +9577,7 @@ dependencies = [ "parcel_selectors", "parcel_sourcemap", "regex", + "rustc-hash 2.1.0", "serde", "smallvec", "swc_core", @@ -9599,6 +9608,7 @@ dependencies = [ "mime_guess", "parking_lot", "pin-project-lite", + "rustc-hash 2.1.0", "serde", "serde_json", "serde_qs", @@ -9737,6 +9747,7 @@ dependencies = [ "mime", "once_cell", "regex", + "rustc-hash 2.1.0", "serde", "serde_with", "turbo-tasks", @@ -9794,6 +9805,7 @@ dependencies = [ "owo-colors 3.5.0", "parking_lot", "regex", + "rustc-hash 2.1.0", "serde", "serde_json", "serde_with", @@ -9887,6 +9899,7 @@ dependencies = [ "anyhow", "once_cell", "regex", + "rustc-hash 2.1.0", "serde", "similar", "turbo-rcstr", @@ -9907,6 +9920,7 @@ dependencies = [ "futures", "indexmap 2.7.1", "once_cell", + "rustc-hash 2.1.0", "serde", "serde_json", "testing", @@ -11547,6 +11561,7 @@ dependencies = [ "num-format", "owo-colors 3.5.0", "plotters", + "rustc-hash 2.1.0", "semver 1.0.23", "serde", "serde_json", diff --git a/crates/napi/src/next_api/utils.rs b/crates/napi/src/next_api/utils.rs index 681f6696a845c..7f9ea3acdc4a6 100644 --- a/crates/napi/src/next_api/utils.rs +++ b/crates/napi/src/next_api/utils.rs @@ -1,6 +1,4 @@ -use std::{ - collections::HashMap, future::Future, ops::Deref, path::PathBuf, sync::Arc, time::Duration, -}; +use std::{future::Future, ops::Deref, path::PathBuf, sync::Arc, time::Duration}; use anyhow::{anyhow, Context, Result}; use napi::{ @@ -8,6 +6,7 @@ use napi::{ threadsafe_function::{ThreadSafeCallContext, ThreadsafeFunction, ThreadsafeFunctionCallMode}, JsFunction, JsObject, JsUnknown, NapiRaw, NapiValue, Status, }; +use rustc_hash::FxHashMap; use serde::Serialize; use turbo_tasks::{ task_statistics::TaskStatisticsApi, trace::TraceRawVcs, OperationVc, ReadRef, TaskId, @@ -412,7 +411,8 @@ impl From for NapiSourcePos { pub struct NapiDiagnostic { pub category: String, pub name: String, - pub payload: HashMap, + #[napi(ts_type = "Record")] + pub payload: FxHashMap, } impl NapiDiagnostic { diff --git a/crates/next-api/Cargo.toml b/crates/next-api/Cargo.toml index 9cfadce352138..4f3ea0327730f 100644 --- a/crates/next-api/Cargo.toml +++ b/crates/next-api/Cargo.toml @@ -20,9 +20,11 @@ indexmap = { workspace = true } next-core = { workspace = true } petgraph = { workspace = true, features = ["serde-1"]} regex = { workspace = true } +rustc-hash = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } shadow-rs = { workspace = true } +swc_core = { workspace = true } tracing = { workspace = true } turbo-rcstr = { workspace = true } turbo-tasks = { workspace = true } @@ -34,11 +36,10 @@ turbopack = { workspace = true } turbopack-browser = { workspace = true } turbopack-cli-utils = { workspace = true } turbopack-core = { workspace = true } -turbopack-env = { workspace = true } turbopack-ecmascript = { workspace = true } +turbopack-env = { workspace = true } turbopack-node = { workspace = true } turbopack-nodejs = { workspace = true } -swc_core = { workspace = true } [build-dependencies] # It is not a mistake this dependency is specified in dep / build-dep both. diff --git a/crates/next-api/src/client_references.rs b/crates/next-api/src/client_references.rs index e64f29119d430..fabf70dafc5ff 100644 --- a/crates/next-api/src/client_references.rs +++ b/crates/next-api/src/client_references.rs @@ -1,11 +1,10 @@ -use std::collections::HashMap; - use anyhow::Result; use next_core::{ self, next_client_reference::{CssClientReferenceModule, EcmascriptClientReferenceModule}, next_server_component::server_component_module::NextServerComponentModule, }; +use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use turbo_tasks::{ debug::ValueDebugFormat, trace::TraceRawVcs, NonLocalValue, ResolvedVc, TryFlatJoinIterExt, Vc, @@ -26,7 +25,7 @@ pub enum ClientReferenceMapType { } #[turbo_tasks::value(transparent)] -pub struct ClientReferencesSet(HashMap>, ClientReferenceMapType>); +pub struct ClientReferencesSet(FxHashMap>, ClientReferenceMapType>); #[turbo_tasks::function] pub async fn map_client_references( diff --git a/crates/next-api/src/loadable_manifest.rs b/crates/next-api/src/loadable_manifest.rs index e05ce595aaab5..63f519f702eb9 100644 --- a/crates/next-api/src/loadable_manifest.rs +++ b/crates/next-api/src/loadable_manifest.rs @@ -1,7 +1,6 @@ -use std::collections::HashMap; - use anyhow::Result; use next_core::{next_manifests::LoadableManifest, util::NextRuntime}; +use rustc_hash::FxHashMap; use turbo_rcstr::RcStr; use turbo_tasks::{ResolvedVc, TryFlatJoinIterExt, ValueToString, Vc}; use turbo_tasks_fs::{File, FileContent, FileSystemPath}; @@ -23,7 +22,7 @@ pub async fn create_react_loadable_manifest( ) -> Result> { let dynamic_import_entries = &*dynamic_import_entries.await?; - let mut loadable_manifest: HashMap = Default::default(); + let mut loadable_manifest: FxHashMap = FxHashMap::default(); for (_, (module_id, chunk_output)) in dynamic_import_entries.into_iter() { let chunk_output = chunk_output.await?; diff --git a/crates/next-api/src/module_graph.rs b/crates/next-api/src/module_graph.rs index d5c0b9451721e..5317c9e138019 100644 --- a/crates/next-api/src/module_graph.rs +++ b/crates/next-api/src/module_graph.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::HashMap}; +use std::borrow::Cow; use anyhow::Result; use next_core::{ @@ -9,6 +9,7 @@ use next_core::{ next_dynamic::NextDynamicEntryModule, next_manifests::ActionLayer, }; +use rustc_hash::FxHashMap; use tracing::Instrument; use turbo_tasks::{ CollectiblesSource, FxIndexMap, FxIndexSet, ResolvedVc, TryFlatJoinIterExt, TryJoinIterExt, Vc, @@ -58,8 +59,8 @@ impl NextDynamicGraph { // This would clone the graph and allow changing the node weights. We can probably get away // with keeping the sidecar information separate from the graph itself, though. // - // let mut reduced_modules: HashMap>, NodeIndex> = - // HashMap::new(); let mut reduced_graph = DiGraph::new(); + // let mut reduced_modules: FxHashMap>, NodeIndex> = + // FxHashMap::default(); let mut reduced_graph = DiGraph::new(); // for idx in graph.node_indices() { // let weight = *graph.node_weight(idx).unwrap(); // let new_idx = reduced_graph.add_node(weight); @@ -112,7 +113,7 @@ impl NextDynamicGraph { let mut result = vec![]; // module -> the client reference entry (if any) - let mut state_map = HashMap::new(); + let mut state_map = FxHashMap::default(); graph.traverse_edges_from_entries(entries, |parent_info, node| { let module = node.module; let Some((parent_node, _)) = parent_info else { @@ -210,7 +211,7 @@ impl ServerActionsGraph { return Ok(Vc::cell(Default::default())); } - let mut result = HashMap::new(); + let mut result = FxHashMap::default(); graph.traverse_from_entry(entry, |node| { if let Some(node_data) = data.get(&node.module) { result.insert(node.module, *node_data); @@ -309,7 +310,7 @@ impl ClientReferencesGraph { graph.traverse_edges_from_entries_topological( entries, // state_map is `module -> Option< the current so parent server component >` - &mut HashMap::new(), + &mut FxHashMap::default(), |parent_info, node, state_map| { let module = node.module; let module_type = data.get(&module); diff --git a/crates/next-api/src/operation.rs b/crates/next-api/src/operation.rs index 77e225aa344ad..a91ff6168c76b 100644 --- a/crates/next-api/src/operation.rs +++ b/crates/next-api/src/operation.rs @@ -1,10 +1,9 @@ use anyhow::Result; -use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use turbo_rcstr::RcStr; use turbo_tasks::{ - debug::ValueDebugFormat, get_effects, trace::TraceRawVcs, CollectiblesSource, NonLocalValue, - OperationVc, ResolvedVc, Vc, + debug::ValueDebugFormat, get_effects, trace::TraceRawVcs, CollectiblesSource, FxIndexMap, + NonLocalValue, OperationVc, ResolvedVc, Vc, }; use turbopack_core::{diagnostics::Diagnostic, issue::IssueDescriptionExt}; @@ -23,7 +22,7 @@ use crate::{ /// This is needed to call `write_to_disk` which expects an `OperationVc`. #[turbo_tasks::value(shared)] pub struct EntrypointsOperation { - pub routes: IndexMap, + pub routes: FxIndexMap, pub middleware: Option, pub instrumentation: Option, pub pages_document_endpoint: OperationVc>, diff --git a/crates/next-api/src/server_actions.rs b/crates/next-api/src/server_actions.rs index 03e4c98acf282..ee2a760a05d46 100644 --- a/crates/next-api/src/server_actions.rs +++ b/crates/next-api/src/server_actions.rs @@ -1,7 +1,4 @@ -use std::{ - collections::{BTreeMap, HashMap}, - io::Write, -}; +use std::{collections::BTreeMap, io::Write}; use anyhow::{bail, Context, Result}; use next_core::{ @@ -10,6 +7,7 @@ use next_core::{ }, util::NextRuntime, }; +use rustc_hash::FxHashMap; use swc_core::{ atoms::Atom, common::comments::Comments, @@ -399,7 +397,7 @@ struct OptionActionMap(Option>); type LayerAndActions = (ActionLayer, ResolvedVc); /// A mapping of every module module containing Server Actions, mapping to its layer and actions. #[turbo_tasks::value(transparent)] -pub struct AllModuleActions(HashMap>, LayerAndActions>); +pub struct AllModuleActions(FxHashMap>, LayerAndActions>); #[turbo_tasks::function] pub async fn map_server_actions(graph: Vc) -> Result> { diff --git a/crates/next-api/src/versioned_content_map.rs b/crates/next-api/src/versioned_content_map.rs index 34f84f215d5e4..9991ef26d2bbb 100644 --- a/crates/next-api/src/versioned_content_map.rs +++ b/crates/next-api/src/versioned_content_map.rs @@ -1,7 +1,6 @@ -use std::collections::{HashMap, HashSet}; - use anyhow::{bail, Result}; use next_core::emit_assets; +use rustc_hash::{FxHashMap, FxHashSet}; use serde::{Deserialize, Serialize}; use turbo_rcstr::RcStr; use turbo_tasks::{ @@ -31,7 +30,7 @@ use turbopack_core::{ struct MapEntry { assets_operation: OperationVc, /// Precomputed map for quick access to output asset by filepath - path_to_asset: HashMap, ResolvedVc>>, + path_to_asset: FxHashMap, ResolvedVc>>, } // HACK: This is technically incorrect because `path_to_asset` contains `ResolvedVc`... @@ -49,7 +48,7 @@ pub struct PathToOutputOperation( /// It may not be 100% correct for the key (`FileSystemPath`) to be in a `ResolvedVc` here, but /// it's impractical to make it an `OperationVc`/`OperationValue`, and it's unlikely to /// change/break? - HashMap, FxIndexSet>>, + FxHashMap, FxIndexSet>>, ); // HACK: This is technically incorrect because the map's key is a `ResolvedVc`... @@ -57,7 +56,7 @@ unsafe impl OperationValue for PathToOutputOperation {} // A precomputed map for quick access to output asset by filepath type OutputOperationToComputeEntry = - HashMap, OperationVc>; + FxHashMap, OperationVc>; #[turbo_tasks::value] pub struct VersionedContentMap { @@ -77,8 +76,8 @@ impl VersionedContentMap { // should be a singleton for each project. pub fn new() -> ResolvedVc { VersionedContentMap { - map_path_to_op: State::new(PathToOutputOperation(HashMap::new())), - map_op_to_compute_entry: State::new(HashMap::new()), + map_path_to_op: State::new(PathToOutputOperation(FxHashMap::default())), + map_op_to_compute_entry: State::new(FxHashMap::default()), } .resolved_cell() } @@ -142,7 +141,7 @@ impl VersionedContentMap { let mut changed = false; // get current map's keys, subtract keys that don't exist in operation - let mut stale_assets = map.0.keys().copied().collect::>(); + let mut stale_assets = map.0.keys().copied().collect::>(); for (k, _) in entries.iter() { let res = map.0.entry(*k).or_default().insert(assets_operation); diff --git a/crates/next-core/src/next_app/metadata/mod.rs b/crates/next-core/src/next_app/metadata/mod.rs index 4ac51aff21c15..b9192ceceddd0 100644 --- a/crates/next-core/src/next_app/metadata/mod.rs +++ b/crates/next-core/src/next_app/metadata/mod.rs @@ -1,7 +1,8 @@ -use std::{collections::HashMap, ops::Deref}; +use std::ops::Deref; use anyhow::Result; use once_cell::sync::Lazy; +use rustc_hash::FxHashMap; use turbo_rcstr::RcStr; use turbo_tasks::Vc; use turbo_tasks_fs::FileSystemPath; @@ -11,9 +12,9 @@ use crate::next_app::{AppPage, PageSegment, PageType}; pub mod image; pub mod route; -pub static STATIC_LOCAL_METADATA: Lazy> = +pub static STATIC_LOCAL_METADATA: Lazy> = Lazy::new(|| { - HashMap::from([ + FxHashMap::from_iter([ ( "icon", &["ico", "jpg", "jpeg", "png", "svg"] as &'static [&'static str], @@ -25,9 +26,9 @@ pub static STATIC_LOCAL_METADATA: Lazy> = +pub static STATIC_GLOBAL_METADATA: Lazy> = Lazy::new(|| { - HashMap::from([ + FxHashMap::from_iter([ ("favicon", &["ico"] as &'static [&'static str]), ("manifest", &["webmanifest", "json"]), ("robots", &["txt"]), @@ -52,7 +53,7 @@ fn match_numbered_metadata(stem: &str) -> Option<(&str, &str)> { fn match_metadata_file<'a>( filename: &'a str, page_extensions: &[RcStr], - metadata: &HashMap<&str, &[&str]>, + metadata: &FxHashMap<&str, &[&str]>, ) -> Option> { let (stem, ext) = filename.split_once('.')?; diff --git a/crates/next-core/src/next_client_reference/visit_client_reference.rs b/crates/next-core/src/next_client_reference/visit_client_reference.rs index 5b1808868d0ab..53b09dfa6c165 100644 --- a/crates/next-core/src/next_client_reference/visit_client_reference.rs +++ b/crates/next-core/src/next_client_reference/visit_client_reference.rs @@ -1,6 +1,7 @@ -use std::{collections::HashSet, future::Future}; +use std::future::Future; use anyhow::Result; +use rustc_hash::FxHashSet; use serde::{Deserialize, Serialize}; use tracing::Instrument; use turbo_rcstr::RcStr; @@ -97,7 +98,7 @@ impl Default for ClientReferenceGraphResult { } #[turbo_tasks::value(shared)] -pub struct VisitedClientReferenceGraphNodes(HashSet); +pub struct VisitedClientReferenceGraphNodes(FxHashSet); #[turbo_tasks::value_impl] impl VisitedClientReferenceGraphNodes { diff --git a/crates/next-core/src/next_config.rs b/crates/next-core/src/next_config.rs index e849e31274989..31dd450d6981c 100644 --- a/crates/next-core/src/next_config.rs +++ b/crates/next-core/src/next_config.rs @@ -1,5 +1,3 @@ -use std::collections::HashSet; - use anyhow::{bail, Context, Result}; use rustc_hash::FxHashSet; use serde::{Deserialize, Deserializer, Serialize}; @@ -1137,7 +1135,7 @@ impl NextConfig { if turbo_rules.is_empty() { return Vc::cell(None); } - let active_conditions = active_conditions.into_iter().collect::>(); + let active_conditions = active_conditions.into_iter().collect::>(); let mut rules = FxIndexMap::default(); for (ext, rule) in turbo_rules.iter() { fn transform_loaders(loaders: &[LoaderItem]) -> ResolvedVc { @@ -1161,7 +1159,7 @@ impl NextConfig { } fn find_rule<'a>( rule: &'a RuleConfigItem, - active_conditions: &HashSet, + active_conditions: &FxHashSet, ) -> FindRuleResult<'a> { match rule { RuleConfigItem::Options(rule) => FindRuleResult::Found(rule), diff --git a/crates/next-core/src/next_edge/route_regex.rs b/crates/next-core/src/next_edge/route_regex.rs index 10365453941d6..e30ede371a2b2 100644 --- a/crates/next-core/src/next_edge/route_regex.rs +++ b/crates/next-core/src/next_edge/route_regex.rs @@ -1,10 +1,9 @@ //! The following code was mostly generated using GTP-4 from //! next.js/packages/next/src/shared/lib/router/utils/route-regex.ts -use std::collections::HashMap; - use once_cell::sync::Lazy; use regex::Regex; +use rustc_hash::FxHashMap; const INTERCEPTION_ROUTE_MARKERS: [&str; 4] = ["(..)(..)", "(.)", "(..)", "(...)"]; const NEXT_QUERY_PARAM_PREFIX: &str = "nxtP"; @@ -19,7 +18,7 @@ pub struct Group { #[derive(Debug)] pub struct RouteRegex { - pub groups: HashMap, + pub groups: FxHashMap, pub regex: String, } @@ -27,7 +26,7 @@ pub struct RouteRegex { pub struct NamedRouteRegex { pub regex: RouteRegex, pub named_regex: String, - pub route_keys: HashMap, + pub route_keys: FxHashMap, } #[derive(Debug)] @@ -83,9 +82,9 @@ fn remove_trailing_slash(route: &str) -> &str { static PARAM_MATCH_REGEX: Lazy = Lazy::new(|| Regex::new(r"\[((?:\[.*\])|.+)\]").unwrap()); -fn get_parametrized_route(route: &str) -> (String, HashMap) { +fn get_parametrized_route(route: &str) -> (String, FxHashMap) { let segments: Vec<&str> = remove_trailing_slash(route)[1..].split('/').collect(); - let mut groups: HashMap = HashMap::new(); + let mut groups: FxHashMap = FxHashMap::default(); let mut group_index = 1; let parameterized_route = segments .iter() @@ -163,7 +162,7 @@ fn build_get_safe_route_key() -> impl FnMut() -> String { fn get_safe_key_from_segment( get_safe_route_key: &mut impl FnMut() -> String, segment: &str, - route_keys: &mut HashMap, + route_keys: &mut FxHashMap, key_prefix: Option<&'static str>, ) -> String { let ParsedParameter { @@ -207,10 +206,10 @@ fn get_safe_key_from_segment( fn get_named_parametrized_route( route: &str, prefix_route_keys: bool, -) -> (String, HashMap) { +) -> (String, FxHashMap) { let segments: Vec<&str> = remove_trailing_slash(route)[1..].split('/').collect(); let get_safe_route_key = &mut build_get_safe_route_key(); - let mut route_keys: HashMap = HashMap::new(); + let mut route_keys: FxHashMap = FxHashMap::default(); let parameterized_route = segments .iter() .map(|segment| { diff --git a/crates/next-core/src/next_font/google/font_fallback.rs b/crates/next-core/src/next_font/google/font_fallback.rs index e67f13ae9c289..272e45aa26517 100644 --- a/crates/next-core/src/next_font/google/font_fallback.rs +++ b/crates/next-core/src/next_font/google/font_fallback.rs @@ -1,8 +1,7 @@ -use std::collections::HashMap; - use anyhow::{Context, Result}; use once_cell::sync::Lazy; use regex::Regex; +use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use turbo_rcstr::RcStr; use turbo_tasks::{trace::TraceRawVcs, NonLocalValue, ResolvedVc, Vc}; @@ -35,7 +34,7 @@ pub(super) struct FontMetricsMapEntry { } #[derive(Deserialize, Debug)] -pub(super) struct FontMetricsMap(pub HashMap); +pub(super) struct FontMetricsMap(pub FxHashMap); #[derive(Debug, PartialEq, Serialize, Deserialize, TraceRawVcs, NonLocalValue)] struct Fallback { diff --git a/crates/next-core/src/next_font/google/mod.rs b/crates/next-core/src/next_font/google/mod.rs index 044dec70cca75..fe29c036d4e0d 100644 --- a/crates/next-core/src/next_font/google/mod.rs +++ b/crates/next-core/src/next_font/google/mod.rs @@ -1,8 +1,9 @@ -use std::{collections::HashMap, path::Path}; +use std::path::Path; use anyhow::{bail, Context, Result}; use futures::FutureExt; use indoc::formatdoc; +use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use turbo_rcstr::RcStr; use turbo_tasks::{Completion, FxIndexMap, ResolvedVc, Value, Vc}; @@ -710,7 +711,8 @@ async fn get_mock_stylesheet( match &val.try_into_single().await? { SingleValue::Single(val) => { - let val: HashMap> = parse_json_with_source_context(val.to_str()?)?; + let val: FxHashMap> = + parse_json_with_source_context(val.to_str()?)?; Ok(val .get(&*stylesheet_url.await?) .context("url not found")? diff --git a/crates/next-core/src/next_import_map.rs b/crates/next-core/src/next_import_map.rs index 45fde778af0b5..e1a5fe3564fbf 100644 --- a/crates/next-core/src/next_import_map.rs +++ b/crates/next-core/src/next_import_map.rs @@ -1,6 +1,7 @@ -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use anyhow::{Context, Result}; +use rustc_hash::FxHashMap; use turbo_rcstr::RcStr; use turbo_tasks::{fxindexmap, FxIndexMap, ResolvedVc, Value, Vc}; use turbo_tasks_fs::{FileSystem, FileSystemPath}; @@ -1051,7 +1052,7 @@ fn export_value_to_import_mapping( value.add_results( conditions, &ConditionValue::Unset, - &mut HashMap::new(), + &mut FxHashMap::default(), &mut result, ); if result.is_empty() { diff --git a/crates/next-core/src/next_manifests/client_reference_manifest.rs b/crates/next-core/src/next_manifests/client_reference_manifest.rs index 2d82cf32bab8d..0b68a7030c0cd 100644 --- a/crates/next-core/src/next_manifests/client_reference_manifest.rs +++ b/crates/next-core/src/next_manifests/client_reference_manifest.rs @@ -1,8 +1,7 @@ -use std::collections::HashMap; - use anyhow::Result; use either::Either; use indoc::formatdoc; +use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use tracing::Instrument; use turbo_rcstr::RcStr; @@ -98,7 +97,7 @@ impl ClientReferenceManifest { let rsc_app_entry_chunks = &*rsc_app_entry_chunks.await?; async fn cached_chunk_paths( - cache: &mut HashMap>, ReadRef>, + cache: &mut FxHashMap>, ReadRef>, chunks: impl Iterator>>, ) -> Result< impl Iterator>, ReadRef)>, @@ -126,18 +125,18 @@ impl ClientReferenceManifest { Either::Right(path) => (chunk, path), })) } - let mut client_chunk_path_cache: HashMap< + let mut client_chunk_path_cache: FxHashMap< ResolvedVc>, ReadRef, - > = HashMap::new(); - let mut ssr_chunk_path_cache: HashMap< + > = FxHashMap::default(); + let mut ssr_chunk_path_cache: FxHashMap< ResolvedVc>, ReadRef, - > = HashMap::new(); - let mut rsc_chunk_path_cache: HashMap< + > = FxHashMap::default(); + let mut rsc_chunk_path_cache: FxHashMap< ResolvedVc>, ReadRef, - > = HashMap::new(); + > = FxHashMap::default(); for app_client_reference in client_references.await?.client_references.iter() { let app_client_reference_ty = app_client_reference.ty(); diff --git a/crates/next-core/src/next_manifests/mod.rs b/crates/next-core/src/next_manifests/mod.rs index cd95db705d029..23ba40a0e477a 100644 --- a/crates/next-core/src/next_manifests/mod.rs +++ b/crates/next-core/src/next_manifests/mod.rs @@ -2,9 +2,8 @@ pub mod client_reference_manifest; -use std::collections::HashMap; - use anyhow::{Context, Result}; +use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use turbo_rcstr::RcStr; use turbo_tasks::{ @@ -23,7 +22,7 @@ use crate::next_config::{CrossOriginConfig, Rewrites, RouteHas}; #[derive(Serialize, Default, Debug)] pub struct PagesManifest { #[serde(flatten)] - pub pages: HashMap, + pub pages: FxHashMap, } #[derive(Debug, Default)] @@ -234,16 +233,16 @@ pub enum Regions { #[derive(Serialize, Default, Debug)] pub struct MiddlewaresManifestV2 { pub sorted_middleware: Vec, - pub middleware: HashMap, + pub middleware: FxHashMap, pub instrumentation: Option, - pub functions: HashMap, + pub functions: FxHashMap, } #[derive(Serialize, Default, Debug)] #[serde(rename_all = "camelCase")] pub struct ReactLoadableManifest { #[serde(flatten)] - pub manifest: HashMap, + pub manifest: FxHashMap, } #[derive(Serialize, Default, Debug)] @@ -256,8 +255,8 @@ pub struct ReactLoadableManifestEntry { #[derive(Serialize, Default, Debug)] #[serde(rename_all = "camelCase")] pub struct NextFontManifest { - pub pages: HashMap>, - pub app: HashMap>, + pub pages: FxHashMap>, + pub app: FxHashMap>, pub app_using_size_adjust: bool, pub pages_using_size_adjust: bool, } @@ -286,9 +285,9 @@ pub struct LoadableManifest { #[serde(rename_all = "camelCase")] pub struct ServerReferenceManifest<'a> { /// A map from hashed action name to the runtime module we that exports it. - pub node: HashMap<&'a str, ActionManifestEntry<'a>>, + pub node: FxHashMap<&'a str, ActionManifestEntry<'a>>, /// A map from hashed action name to the runtime module we that exports it. - pub edge: HashMap<&'a str, ActionManifestEntry<'a>>, + pub edge: FxHashMap<&'a str, ActionManifestEntry<'a>>, } #[derive(Serialize, Default, Debug)] @@ -296,9 +295,9 @@ pub struct ServerReferenceManifest<'a> { pub struct ActionManifestEntry<'a> { /// A mapping from the page that uses the server action to the runtime /// module that exports it. - pub workers: HashMap<&'a str, ActionManifestWorkerEntry<'a>>, + pub workers: FxHashMap<&'a str, ActionManifestWorkerEntry<'a>>, - pub layer: HashMap<&'a str, ActionLayer>, + pub layer: FxHashMap<&'a str, ActionLayer>, } #[derive(Serialize, Debug)] @@ -346,22 +345,22 @@ pub struct ClientReferenceManifest { pub client_modules: ManifestNode, /// Mapping of client module ID to corresponding SSR module ID and required /// SSR chunks. - pub ssr_module_mapping: HashMap, + pub ssr_module_mapping: FxHashMap, /// Same as `ssr_module_mapping`, but for Edge SSR. #[serde(rename = "edgeSSRModuleMapping")] - pub edge_ssr_module_mapping: HashMap, + pub edge_ssr_module_mapping: FxHashMap, /// Mapping of client module ID to corresponding RSC module ID and required /// RSC chunks. - pub rsc_module_mapping: HashMap, + pub rsc_module_mapping: FxHashMap, /// Same as `rsc_module_mapping`, but for Edge RSC. #[serde(rename = "edgeRscModuleMapping")] - pub edge_rsc_module_mapping: HashMap, + pub edge_rsc_module_mapping: FxHashMap, /// Mapping of server component path to required CSS client chunks. #[serde(rename = "entryCSSFiles")] - pub entry_css_files: HashMap>, + pub entry_css_files: FxHashMap>, /// Mapping of server component path to required JS client chunks. #[serde(rename = "entryJSFiles")] - pub entry_js_files: HashMap>, + pub entry_js_files: FxHashMap>, } #[derive(Serialize, Debug, Clone, Eq, Hash, PartialEq)] @@ -384,7 +383,7 @@ pub struct ModuleLoading { pub struct ManifestNode { /// Mapping of export name to manifest node entry. #[serde(flatten)] - pub module_exports: HashMap, + pub module_exports: FxHashMap, } #[derive(Serialize, Debug, Clone)] @@ -491,7 +490,7 @@ pub struct ClientBuildManifest<'a> { pub sorted_pages: &'a [RcStr], #[serde(flatten)] - pub pages: HashMap>, + pub pages: FxHashMap>, } #[cfg(test)] diff --git a/crates/next-core/src/next_shared/resolve.rs b/crates/next-core/src/next_shared/resolve.rs index 4ce77765db139..e484db46657ba 100644 --- a/crates/next-core/src/next_shared/resolve.rs +++ b/crates/next-core/src/next_shared/resolve.rs @@ -1,7 +1,6 @@ -use std::collections::HashMap; - use anyhow::Result; use lazy_static::lazy_static; +use rustc_hash::FxHashMap; use turbo_rcstr::RcStr; use turbo_tasks::{ResolvedVc, Value, Vc}; use turbo_tasks_fs::{glob::Glob, FileSystemPath}; @@ -24,7 +23,7 @@ use crate::{next_server::ServerContextType, next_telemetry::ModuleFeatureTelemet lazy_static! { // Set of the features we want to track, following existing references in webpack/plugins/telemetry-plugin. - static ref FEATURE_MODULES: HashMap<&'static str, Vec<&'static str>> = HashMap::from([ + static ref FEATURE_MODULES: FxHashMap<&'static str, Vec<&'static str>> = FxHashMap::from_iter([ ( "next", vec![ diff --git a/crates/next-core/src/url_node.rs b/crates/next-core/src/url_node.rs index 61466d3f80fa8..60296cba7c954 100644 --- a/crates/next-core/src/url_node.rs +++ b/crates/next-core/src/url_node.rs @@ -1,8 +1,7 @@ //! The following code is adapted from sorted-routes.ts using GPT-4 and human //! review. -use std::collections::HashMap; - +use rustc_hash::FxHashMap; use thiserror::Error; #[derive(Debug, Error)] @@ -43,7 +42,7 @@ pub enum UrlNodeError { pub struct UrlNode { placeholder: bool, - children: HashMap, + children: FxHashMap, slug_name: Option, rest_slug_name: Option, optional_rest_slug_name: Option, @@ -59,7 +58,7 @@ impl UrlNode { pub fn new() -> UrlNode { UrlNode { placeholder: true, - children: HashMap::new(), + children: FxHashMap::default(), slug_name: None, rest_slug_name: None, optional_rest_slug_name: None, diff --git a/crates/next-custom-transforms/src/lib.rs b/crates/next-custom-transforms/src/lib.rs index fa2c99a578a4e..0e2a59fd72833 100644 --- a/crates/next-custom-transforms/src/lib.rs +++ b/crates/next-custom-transforms/src/lib.rs @@ -32,6 +32,13 @@ DEALINGS IN THE SOFTWARE. #![feature(arbitrary_self_types)] #![feature(arbitrary_self_types_pointers)] +use std::hash::BuildHasherDefault; + +use indexmap::IndexMap; +use rustc_hash::FxHasher; + pub mod chain_transforms; mod linter; pub mod transforms; + +type FxIndexMap = IndexMap>; diff --git a/crates/next-custom-transforms/src/transforms/page_static_info/collect_exports_visitor.rs b/crates/next-custom-transforms/src/transforms/page_static_info/collect_exports_visitor.rs index 4008c2bf17ec7..294f8f93c0403 100644 --- a/crates/next-custom-transforms/src/transforms/page_static_info/collect_exports_visitor.rs +++ b/crates/next-custom-transforms/src/transforms/page_static_info/collect_exports_visitor.rs @@ -1,6 +1,7 @@ -use std::collections::HashSet; +use std::iter::FromIterator; use lazy_static::lazy_static; +use rustc_hash::FxHashSet; use swc_core::{ atoms::atom, ecma::{ @@ -15,7 +16,7 @@ use swc_core::{ use super::{ExportInfo, ExportInfoWarning}; lazy_static! { - static ref EXPORTS_SET: HashSet<&'static str> = HashSet::from([ + static ref EXPORTS_SET: FxHashSet<&'static str> = FxHashSet::from_iter([ "getStaticProps", "getServerSideProps", "generateImageMetadata", diff --git a/crates/next-custom-transforms/src/transforms/react_server_components.rs b/crates/next-custom-transforms/src/transforms/react_server_components.rs index 3b1c0f7cb113e..2b5a6878f42ce 100644 --- a/crates/next-custom-transforms/src/transforms/react_server_components.rs +++ b/crates/next-custom-transforms/src/transforms/react_server_components.rs @@ -1,14 +1,14 @@ use std::{ - collections::HashMap, fmt::{self, Display}, + iter::FromIterator, path::PathBuf, rc::Rc, sync::Arc, }; -use indexmap::IndexMap; use once_cell::sync::Lazy; use regex::Regex; +use rustc_hash::FxHashMap; use serde::Deserialize; use swc_core::{ common::{ @@ -29,6 +29,7 @@ use swc_core::{ }; use super::{cjs_finder::contains_cjs, import_analyzer::ImportMap}; +use crate::FxIndexMap; #[derive(Clone, Debug, Deserialize)] #[serde(untagged)] @@ -544,10 +545,10 @@ struct ReactServerComponentValidator { filepath: String, app_dir: Option, invalid_server_imports: Vec, - invalid_server_lib_apis_mapping: HashMap<&'static str, Vec<&'static str>>, - deprecated_apis_mapping: HashMap<&'static str, Vec<&'static str>>, + invalid_server_lib_apis_mapping: FxHashMap<&'static str, Vec<&'static str>>, + deprecated_apis_mapping: FxHashMap<&'static str, Vec<&'static str>>, invalid_client_imports: Vec, - invalid_client_lib_apis_mapping: HashMap<&'static str, Vec<&'static str>>, + invalid_client_lib_apis_mapping: FxHashMap<&'static str, Vec<&'static str>>, pub directive_import_collection: Option<(bool, bool, RcVec, RcVec)>, imports: ImportMap, } @@ -573,7 +574,7 @@ impl ReactServerComponentValidator { // react -> [apis] // react-dom -> [apis] // next/navigation -> [apis] - invalid_server_lib_apis_mapping: [ + invalid_server_lib_apis_mapping: FxHashMap::from_iter([ ( "react", vec![ @@ -618,9 +619,8 @@ impl ReactServerComponentValidator { "ServerInsertedHTMLContext", ], ), - ] - .into(), - deprecated_apis_mapping: [("next/server", vec!["ImageResponse"])].into(), + ]), + deprecated_apis_mapping: FxHashMap::from_iter([("next/server", vec!["ImageResponse"])]), invalid_server_imports: vec![ JsWord::from("client-only"), @@ -631,7 +631,7 @@ impl ReactServerComponentValidator { invalid_client_imports: vec![JsWord::from("server-only"), JsWord::from("next/headers")], - invalid_client_lib_apis_mapping: [("next/server", vec!["after"])].into(), + invalid_client_lib_apis_mapping: FxHashMap::from_iter([("next/server", vec!["after"])]), imports: ImportMap::default(), } } @@ -781,8 +781,8 @@ impl ReactServerComponentValidator { let is_layout_or_page = RE.is_match(&self.filepath); if is_layout_or_page { - let mut possibly_invalid_exports: IndexMap = - IndexMap::new(); + let mut possibly_invalid_exports: FxIndexMap = + FxIndexMap::default(); let mut collect_possibly_invalid_exports = |export_name: &str, span: &Span| match export_name { diff --git a/crates/next-custom-transforms/src/transforms/server_actions.rs b/crates/next-custom-transforms/src/transforms/server_actions.rs index 270255342187f..a892f85ab7cda 100644 --- a/crates/next-custom-transforms/src/transforms/server_actions.rs +++ b/crates/next-custom-transforms/src/transforms/server_actions.rs @@ -1,6 +1,6 @@ use std::{ cell::RefCell, - collections::{hash_map, BTreeMap, HashSet}, + collections::{hash_map, BTreeMap}, convert::{TryFrom, TryInto}, mem::{replace, take}, rc::Rc, @@ -161,7 +161,7 @@ pub fn server_actions( private_ctxt: SyntaxContext::empty().apply_mark(Mark::new()), arrow_or_fn_expr_ident: None, - exported_local_ids: HashSet::new(), + exported_local_ids: FxHashSet::default(), use_cache_telemetry_tracker, }) @@ -218,7 +218,7 @@ struct ServerActions { private_ctxt: SyntaxContext, arrow_or_fn_expr_ident: Option, - exported_local_ids: HashSet, + exported_local_ids: FxHashSet, use_cache_telemetry_tracker: Rc>>, } diff --git a/crates/next-error-code-swc-plugin/Cargo.lock b/crates/next-error-code-swc-plugin/Cargo.lock index ba027ff9919d4..b795f628f807e 100644 --- a/crates/next-error-code-swc-plugin/Cargo.lock +++ b/crates/next-error-code-swc-plugin/Cargo.lock @@ -496,7 +496,7 @@ dependencies = [ "new_debug_unreachable", "once_cell", "phf", - "rustc-hash", + "rustc-hash 1.1.0", "triomphe", ] @@ -776,6 +776,7 @@ name = "next-error-code-swc-plugin" version = "0.1.0" dependencies = [ "md5", + "rustc-hash 2.1.0", "serde", "serde_json", "swc_core", @@ -1112,6 +1113,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" + [[package]] name = "rustc_version" version = "0.2.3" @@ -1301,7 +1308,7 @@ dependencies = [ "data-encoding", "debugid", "if_chain", - "rustc-hash", + "rustc-hash 1.1.0", "rustc_version", "serde", "serde_json", @@ -1361,7 +1368,7 @@ dependencies = [ "bumpalo", "hashbrown 0.14.5", "ptr_meta", - "rustc-hash", + "rustc-hash 1.1.0", "triomphe", ] @@ -1375,7 +1382,7 @@ dependencies = [ "hstr", "once_cell", "rkyv", - "rustc-hash", + "rustc-hash 1.1.0", "serde", ] @@ -1397,7 +1404,7 @@ dependencies = [ "once_cell", "parking_lot", "rkyv", - "rustc-hash", + "rustc-hash 1.1.0", "serde", "siphasher", "sourcemap", @@ -1529,7 +1536,7 @@ dependencies = [ "indexmap", "once_cell", "phf", - "rustc-hash", + "rustc-hash 1.1.0", "serde", "smallvec", "swc_atoms", @@ -1576,7 +1583,7 @@ dependencies = [ "indexmap", "num_cpus", "once_cell", - "rustc-hash", + "rustc-hash 1.1.0", "ryu-js", "swc_atoms", "swc_common", diff --git a/crates/next-error-code-swc-plugin/Cargo.toml b/crates/next-error-code-swc-plugin/Cargo.toml index b4e8649774dd3..8f2ef123802de 100644 --- a/crates/next-error-code-swc-plugin/Cargo.toml +++ b/crates/next-error-code-swc-plugin/Cargo.toml @@ -7,7 +7,8 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -swc_core = { version = "5.0.*", features = ["ecma_plugin_transform"] } -serde_json = "1.0" +md5 = "0.7" +rustc-hash = "2.1.0" serde = "1.0" -md5 = "0.7" \ No newline at end of file +serde_json = "1.0" +swc_core = { version = "5.0.*", features = ["ecma_plugin_transform"] } diff --git a/crates/next-error-code-swc-plugin/src/lib.rs b/crates/next-error-code-swc-plugin/src/lib.rs index b7c8f1091b969..6741c214c8f10 100644 --- a/crates/next-error-code-swc-plugin/src/lib.rs +++ b/crates/next-error-code-swc-plugin/src/lib.rs @@ -1,12 +1,13 @@ -use std::{collections::HashMap, fs}; +use std::fs; +use rustc_hash::FxHashMap; use swc_core::{ ecma::{ast::*, transforms::testing::test_inline, visit::*}, plugin::{plugin_transform, proxies::TransformPluginProgramMetadata}, }; pub struct TransformVisitor { - errors: HashMap, + errors: FxHashMap, } #[derive(serde::Serialize)] @@ -240,7 +241,7 @@ pub fn process_transform( ) -> Program { let errors_json = fs::read_to_string("/cwd/errors.json") .unwrap_or_else(|e| panic!("failed to read errors.json: {}", e)); - let errors: HashMap = serde_json::from_str(&errors_json) + let errors: FxHashMap = serde_json::from_str(&errors_json) .unwrap_or_else(|e| panic!("failed to parse errors.json: {}", e)); let mut visitor = TransformVisitor { errors }; @@ -252,7 +253,7 @@ pub fn process_transform( test_inline!( Default::default(), |_| visit_mut_pass(TransformVisitor { - errors: HashMap::from([ + errors: FxHashMap::from_iter([ ("1".to_string(), "Failed to fetch user %s: %s".to_string()), ("2".to_string(), "Request failed: %s".to_string()), ("3".to_string(), "Generic error".to_string()), diff --git a/turbopack/crates/turbo-prehash/src/lib.rs b/turbopack/crates/turbo-prehash/src/lib.rs index bf187fd72602c..8fedc9074ef21 100644 --- a/turbopack/crates/turbo-prehash/src/lib.rs +++ b/turbopack/crates/turbo-prehash/src/lib.rs @@ -10,17 +10,18 @@ //! # Example //! //! ``` -//! use turbo_prehash::{BuildHasherExt, PreHashed}; -//! use std::collections::HashMap; //! use std::hash::{BuildHasherDefault, RandomState, Hash}; //! +//! use rustc_hash::FxHashMap; +//! use turbo_prehash::{BuildHasherExt, PreHashed}; +//! //! /// hash a key, returning a prehashed value //! fn hash_key(key: T) -> PreHashed { //! RandomState::new().prehash(key) //! } //! //! // create hashmap to hold pre-hashed values -//! let mut map: HashMap, String> = Default::default(); +//! let mut map: FxHashMap, String> = FxHashMap::default(); //! //! // insert a prehashed value //! let hashed_key = hash_key("hello".to_string()); diff --git a/turbopack/crates/turbo-static/Cargo.toml b/turbopack/crates/turbo-static/Cargo.toml index 699c00f64f88c..cba0a71e6805a 100644 --- a/turbopack/crates/turbo-static/Cargo.toml +++ b/turbopack/crates/turbo-static/Cargo.toml @@ -13,6 +13,7 @@ itertools.workspace = true lsp-server = "0.7.6" lsp-types = "0.95.1" proc-macro2 = { workspace = true, features = ["span-locations"] } +rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json.workspace = true serde_path_to_error = "0.1.16" diff --git a/turbopack/crates/turbo-static/src/call_resolver.rs b/turbopack/crates/turbo-static/src/call_resolver.rs index fd18d7361c2ef..e0a148ca346ec 100644 --- a/turbopack/crates/turbo-static/src/call_resolver.rs +++ b/turbopack/crates/turbo-static/src/call_resolver.rs @@ -1,4 +1,6 @@ -use std::{collections::HashMap, fs::OpenOptions, path::PathBuf}; +use std::{fs::OpenOptions, path::PathBuf}; + +use rustc_hash::FxHashMap; use crate::{lsp_client::RAClient, Identifier, IdentifierReference}; @@ -7,7 +9,7 @@ use crate::{lsp_client::RAClient, Identifier, IdentifierReference}; /// store. pub struct CallResolver<'a> { client: &'a mut RAClient, - state: HashMap>, + state: FxHashMap>, path: Option, } @@ -26,7 +28,7 @@ impl Drop for CallResolver<'_> { impl<'a> CallResolver<'a> { pub fn new(client: &'a mut RAClient, path: Option) -> Self { - // load bincode-encoded HashMap from path + // load bincode-encoded FxHashMap from path let state = path .as_ref() .and_then(|path| { @@ -38,7 +40,7 @@ impl<'a> CallResolver<'a> { .open(path) .unwrap(); let reader = std::io::BufReader::new(file); - bincode::deserialize_from::<_, HashMap>>( + bincode::deserialize_from::<_, FxHashMap>>( reader, ) .inspect_err(|_| { diff --git a/turbopack/crates/turbo-static/src/main.rs b/turbopack/crates/turbo-static/src/main.rs index e2cb14266657e..8b996f62c08c5 100644 --- a/turbopack/crates/turbo-static/src/main.rs +++ b/turbopack/crates/turbo-static/src/main.rs @@ -1,5 +1,4 @@ use std::{ - collections::{HashMap, HashSet}, error::Error, fs, path::PathBuf, @@ -13,6 +12,7 @@ use call_resolver::CallResolver; use clap::Parser; use identifier::{Identifier, IdentifierReference}; use itertools::Itertools; +use rustc_hash::{FxHashMap, FxHashSet}; use syn::visit::Visit; use visitor::CallingStyleVisitor; @@ -75,8 +75,8 @@ fn main() -> Result<(), Box> { /// search the given folders recursively and attempt to find all tasks inside #[tracing::instrument(skip_all)] -fn get_all_tasks(folders: &[PathBuf]) -> HashMap> { - let mut out = HashMap::new(); +fn get_all_tasks(folders: &[PathBuf]) -> FxHashMap> { + let mut out = FxHashMap::default(); for folder in folders { let walker = ignore::Walk::new(folder); @@ -139,18 +139,18 @@ fn get_all_tasks(folders: &[PathBuf]) -> HashMap> { /// Given a list of tasks, get all the tasks that call that one fn resolve_tasks( - tasks: &mut HashMap>, + tasks: &mut FxHashMap>, client: &mut CallResolver, halt: Arc, -) -> HashMap> { +) -> FxHashMap> { tracing::info!( "found {} tasks, of which {} cached", tasks.len(), client.cached_count() ); - let mut unresolved = tasks.keys().cloned().collect::>(); - let mut resolved = HashMap::new(); + let mut unresolved = tasks.keys().cloned().collect::>(); + let mut resolved = FxHashMap::default(); while let Some(top) = unresolved.iter().next().cloned() { unresolved.remove(&top); @@ -183,8 +183,8 @@ fn resolve_tasks( /// returns a list of pairs with a task, the task that calls it, and the calling /// style fn resolve_concurrency( - task_list: &HashMap>, - dep_tree: &HashMap>, // pairs of tasks and call trees + task_list: &FxHashMap>, + dep_tree: &FxHashMap>, // pairs of tasks and call trees halt: Arc, ) -> Vec<(Identifier, Identifier, CallingStyle)> { // println!("{:?}", dep_tree); @@ -240,13 +240,13 @@ fn resolve_concurrency( /// Write the dep tree into the given file using cypher syntax fn write_dep_tree( - task_list: &HashMap>, + task_list: &FxHashMap>, dep_tree: Vec<(Identifier, Identifier, CallingStyle)>, out: &std::path::Path, ) { use std::io::Write; - let mut node_ids = HashMap::new(); + let mut node_ids = FxHashMap::default(); let mut counter = 0; let mut file = std::fs::File::create(out).unwrap(); @@ -259,7 +259,7 @@ fn write_dep_tree( .iter() .flat_map(|(dest, src, _)| [(src, &empty), (dest, &empty)]) .chain(task_list) - .collect::>(); + .collect::>(); for (ident, tags) in node_list { counter += 1; diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/mod.rs b/turbopack/crates/turbo-tasks-backend/src/backend/mod.rs index c32c6dda5c94c..2007d15bbf996 100644 --- a/turbopack/crates/turbo-tasks-backend/src/backend/mod.rs +++ b/turbopack/crates/turbo-tasks-backend/src/backend/mod.rs @@ -5,7 +5,6 @@ mod storage; use std::{ borrow::Cow, - collections::{HashMap, HashSet}, future::Future, hash::BuildHasherDefault, mem::take, @@ -20,7 +19,7 @@ use std::{ use anyhow::{bail, Result}; use auto_hash_map::{AutoMap, AutoSet}; use parking_lot::{Condvar, Mutex}; -use rustc_hash::FxHasher; +use rustc_hash::{FxHashMap, FxHashSet, FxHasher}; use smallvec::smallvec; use tokio::time::{Duration, Instant}; use turbo_tasks::{ @@ -67,14 +66,14 @@ const SNAPSHOT_REQUESTED_BIT: usize = 1 << (usize::BITS - 1); struct SnapshotRequest { snapshot_requested: bool, - suspended_operations: HashSet>, + suspended_operations: FxHashSet>, } impl SnapshotRequest { fn new() -> Self { Self { snapshot_requested: false, - suspended_operations: HashSet::new(), + suspended_operations: FxHashSet::default(), } } } @@ -1196,7 +1195,7 @@ impl TurboTasksBackendInner { let _ = stateful; // handle cell counters: update max index and remove cells that are no longer used - let mut old_counters: HashMap<_, _> = + let mut old_counters: FxHashMap<_, _> = get_many!(task, CellTypeMaxIndex { cell_type } max_index => (cell_type, *max_index)); for (&cell_type, &max_index) in cell_counters.iter() { if let Some(old_max_index) = old_counters.remove(&cell_type) { diff --git a/turbopack/crates/turbo-tasks-build/Cargo.toml b/turbopack/crates/turbo-tasks-build/Cargo.toml index 10c91dfeb8798..9e41876fd13b5 100644 --- a/turbopack/crates/turbo-tasks-build/Cargo.toml +++ b/turbopack/crates/turbo-tasks-build/Cargo.toml @@ -16,5 +16,6 @@ anyhow = { workspace = true } cargo-lock = "8.0.2" glob = "0.3.0" quote = { workspace = true } +rustc-hash = { workspace = true } syn = { workspace = true, features = ["full"] } turbo-tasks-macros-shared = { workspace = true } diff --git a/turbopack/crates/turbo-tasks-build/src/lib.rs b/turbopack/crates/turbo-tasks-build/src/lib.rs index 0890594afb8bd..5065a025a1c8e 100644 --- a/turbopack/crates/turbo-tasks-build/src/lib.rs +++ b/turbopack/crates/turbo-tasks-build/src/lib.rs @@ -1,5 +1,4 @@ use std::{ - collections::{HashMap, HashSet}, env::{self, current_dir}, fmt::{Display, Write}, fs::read_dir, @@ -10,6 +9,7 @@ use std::{ use anyhow::{Context, Result}; use glob::glob; use quote::ToTokens; +use rustc_hash::{FxHashMap, FxHashSet}; use syn::{ parse_quote, Attribute, Ident, Item, ItemEnum, ItemFn, ItemImpl, ItemMacro, ItemMod, ItemStruct, ItemTrait, TraitItem, TraitItemMethod, @@ -98,7 +98,7 @@ pub fn generate_register() { let prefix = format!("{crate_name}@{hash}::"); let mut register_code = String::new(); - let mut values = HashMap::new(); + let mut values = FxHashMap::default(); let out_file = out_dir.join(filename); @@ -184,7 +184,7 @@ pub fn rerun_if_glob(globs: &str, root: &str) { let globs = cwd.join(globs.replace('/', PATH_SEP.to_string().as_str())); let root = cwd.join(root.replace('/', PATH_SEP.to_string().as_str())); println!("cargo:rerun-if-changed={}", root.display()); - let mut seen = HashSet::from([root]); + let mut seen = FxHashSet::from_iter([root]); for entry in glob(globs.to_str().unwrap()).unwrap() { let path = entry.unwrap(); for ancestor in path.ancestors() { @@ -225,7 +225,7 @@ struct RegisterContext<'a> { prefix: &'a str, register: &'a mut String, - values: &'a mut HashMap, + values: &'a mut FxHashMap, } impl RegisterContext<'_> { diff --git a/turbopack/crates/turbo-tasks-fs/Cargo.toml b/turbopack/crates/turbo-tasks-fs/Cargo.toml index 175500e8198fd..bf2dfe8302136 100644 --- a/turbopack/crates/turbo-tasks-fs/Cargo.toml +++ b/turbopack/crates/turbo-tasks-fs/Cargo.toml @@ -40,6 +40,7 @@ mime = { workspace = true } notify = { workspace = true } parking_lot = { workspace = true } rayon = { workspace = true } +rustc-hash = { workspace = true } serde = { workspace = true, features = ["rc"] } serde_bytes = { workspace = true } serde_json = { workspace = true } diff --git a/turbopack/crates/turbo-tasks-fs/src/invalidator_map.rs b/turbopack/crates/turbo-tasks-fs/src/invalidator_map.rs index 7fd36737a05b9..79161216260ba 100644 --- a/turbopack/crates/turbo-tasks-fs/src/invalidator_map.rs +++ b/turbopack/crates/turbo-tasks-fs/src/invalidator_map.rs @@ -1,15 +1,13 @@ -use std::{ - collections::{HashMap, HashSet}, - sync::{LockResult, Mutex, MutexGuard}, -}; +use std::sync::{LockResult, Mutex, MutexGuard}; use concurrent_queue::ConcurrentQueue; +use rustc_hash::{FxHashMap, FxHashSet}; use serde::{de::Visitor, Deserialize, Serialize}; use turbo_tasks::Invalidator; pub struct InvalidatorMap { queue: ConcurrentQueue<(String, Invalidator)>, - map: Mutex>>, + map: Mutex>>, } impl Default for InvalidatorMap { @@ -26,7 +24,7 @@ impl InvalidatorMap { Self::default() } - pub fn lock(&self) -> LockResult>>> { + pub fn lock(&self) -> LockResult>>> { let mut guard = self.map.lock()?; while let Ok((key, value)) = self.queue.pop() { guard.entry(key).or_default().insert(value); diff --git a/turbopack/crates/turbo-tasks-fs/src/lib.rs b/turbopack/crates/turbo-tasks-fs/src/lib.rs index 7b318902f427d..ccc522bd7c134 100644 --- a/turbopack/crates/turbo-tasks-fs/src/lib.rs +++ b/turbopack/crates/turbo-tasks-fs/src/lib.rs @@ -27,7 +27,6 @@ mod watcher; use std::{ borrow::Cow, cmp::{min, Ordering}, - collections::HashSet, fmt::{self, Debug, Display, Formatter, Write as _}, fs::FileType, future::Future, @@ -50,6 +49,7 @@ use mime::Mime; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use read_glob::read_glob; pub use read_glob::ReadGlobResult; +use rustc_hash::FxHashSet; use serde::{Deserialize, Serialize}; use serde_json::Value; use tokio::{ @@ -261,9 +261,10 @@ impl DiskFileSystemInner { &self, path: &Path, invalidator: Invalidator, - ) -> Result> { + ) -> Result> { let mut invalidator_map = self.invalidator_map.lock().unwrap(); - let old_invalidators = invalidator_map.insert(path_to_key(path), [invalidator].into()); + let old_invalidators = + invalidator_map.insert(path_to_key(path), FxHashSet::from_iter([invalidator])); drop(invalidator_map); #[cfg(not(any(target_os = "macos", target_os = "windows")))] if let Some(dir) = path.parent() { @@ -329,7 +330,7 @@ impl DiskFileSystemInner { }); } - fn invalidate_from_write(&self, full_path: &Path, invalidators: HashSet) { + fn invalidate_from_write(&self, full_path: &Path, invalidators: FxHashSet) { if !invalidators.is_empty() { if let Some(path) = format_absolute_fs_path(full_path, &self.name, self.root_path()) { if invalidators.len() == 1 { diff --git a/turbopack/crates/turbo-tasks-fs/src/mutex_map.rs b/turbopack/crates/turbo-tasks-fs/src/mutex_map.rs index 4b9ae10fb8ac2..8e32c55be2086 100644 --- a/turbopack/crates/turbo-tasks-fs/src/mutex_map.rs +++ b/turbopack/crates/turbo-tasks-fs/src/mutex_map.rs @@ -1,21 +1,18 @@ -use std::{ - collections::{hash_map::Entry, HashMap}, - hash::Hash, - marker::PhantomData, -}; +use std::{collections::hash_map::Entry, hash::Hash, marker::PhantomData}; use parking_lot::Mutex; +use rustc_hash::FxHashMap; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use turbo_tasks::event::Event; pub struct MutexMap { - map: Mutex>>, + map: Mutex>>, } impl Default for MutexMap { fn default() -> Self { Self { - map: Mutex::new(HashMap::new()), + map: Mutex::new(FxHashMap::default()), } } } diff --git a/turbopack/crates/turbo-tasks-fs/src/read_glob.rs b/turbopack/crates/turbo-tasks-fs/src/read_glob.rs index 501b1b0adc8ee..ba4781f3095f9 100644 --- a/turbopack/crates/turbo-tasks-fs/src/read_glob.rs +++ b/turbopack/crates/turbo-tasks-fs/src/read_glob.rs @@ -1,6 +1,5 @@ -use std::collections::HashMap; - use anyhow::Result; +use rustc_hash::FxHashMap; use turbo_rcstr::RcStr; use turbo_tasks::{ResolvedVc, Vc}; @@ -9,8 +8,8 @@ use crate::{glob::Glob, DirectoryContent, DirectoryEntry, FileSystemPath}; #[turbo_tasks::value] #[derive(Default, Debug)] pub struct ReadGlobResult { - pub results: HashMap, - pub inner: HashMap>, + pub results: FxHashMap, + pub inner: FxHashMap>, } /// Reads matches of a glob pattern. diff --git a/turbopack/crates/turbo-tasks-fs/src/watcher.rs b/turbopack/crates/turbo-tasks-fs/src/watcher.rs index 8fd7cfa142e1d..4afcd44933699 100644 --- a/turbopack/crates/turbo-tasks-fs/src/watcher.rs +++ b/turbopack/crates/turbo-tasks-fs/src/watcher.rs @@ -1,5 +1,4 @@ use std::{ - collections::{HashMap, HashSet}, mem::take, path::{Path, PathBuf}, sync::{ @@ -15,6 +14,7 @@ use notify::{ Config, EventKind, PollWatcher, RecommendedWatcher, RecursiveMode, Watcher, }; use rayon::iter::{IntoParallelIterator, ParallelIterator}; +use rustc_hash::{FxHashMap, FxHashSet}; use serde::{Deserialize, Serialize}; use tracing::instrument; use turbo_tasks::{spawn_thread, Invalidator}; @@ -240,13 +240,13 @@ impl DiskWatcher { inner: Arc, report_invalidation_reason: bool, ) { - let mut batched_invalidate_path = HashSet::new(); - let mut batched_invalidate_path_dir = HashSet::new(); - let mut batched_invalidate_path_and_children = HashSet::new(); - let mut batched_invalidate_path_and_children_dir = HashSet::new(); + let mut batched_invalidate_path = FxHashSet::default(); + let mut batched_invalidate_path_dir = FxHashSet::default(); + let mut batched_invalidate_path_and_children = FxHashSet::default(); + let mut batched_invalidate_path_and_children_dir = FxHashSet::default(); #[cfg(not(any(target_os = "macos", target_os = "windows")))] - let mut batched_new_paths = HashSet::new(); + let mut batched_new_paths = FxHashSet::default(); 'outer: loop { let mut event = rx.recv().or(Err(TryRecvError::Disconnected)); @@ -459,7 +459,7 @@ fn invalidate( fn invalidate_path( inner: &DiskFileSystemInner, report_invalidation_reason: bool, - invalidator_map: &mut HashMap>, + invalidator_map: &mut FxHashMap>, paths: impl Iterator, ) { for path in paths { @@ -475,7 +475,7 @@ fn invalidate_path( fn invalidate_path_and_children_execute( inner: &DiskFileSystemInner, report_invalidation_reason: bool, - invalidator_map: &mut HashMap>, + invalidator_map: &mut FxHashMap>, paths: impl Iterator, ) { for path in paths { diff --git a/turbopack/crates/turbo-tasks-macros/Cargo.toml b/turbopack/crates/turbo-tasks-macros/Cargo.toml index a1ff47abce163..e4c2e52b4ccea 100644 --- a/turbopack/crates/turbo-tasks-macros/Cargo.toml +++ b/turbopack/crates/turbo-tasks-macros/Cargo.toml @@ -18,5 +18,6 @@ proc-macro-error = "1.0.4" proc-macro2 = { workspace = true } quote = { workspace = true } regex = { workspace = true } +rustc-hash = { workspace = true } syn = { workspace = true, features = ["full", "extra-traits", "visit-mut"] } turbo-tasks-macros-shared = { workspace = true } diff --git a/turbopack/crates/turbo-tasks-macros/src/func.rs b/turbopack/crates/turbo-tasks-macros/src/func.rs index 6d6981253ef38..0930edae1ef07 100644 --- a/turbopack/crates/turbo-tasks-macros/src/func.rs +++ b/turbopack/crates/turbo-tasks-macros/src/func.rs @@ -1,7 +1,8 @@ -use std::{borrow::Cow, collections::HashSet}; +use std::borrow::Cow; use proc_macro2::{Ident, Span, TokenStream}; use quote::{quote, quote_spanned, ToTokens}; +use rustc_hash::FxHashSet; use syn::{ parenthesized, parse::{Parse, ParseStream}, @@ -753,7 +754,7 @@ pub struct FunctionArguments { /// /// This should only be used by the task that directly performs the IO. Tasks that transitively /// perform IO should not be manually annotated. - io_markers: HashSet, + io_markers: FxHashSet, /// Should the function return an `OperationVc` instead of a `Vc`? Also ensures that all /// arguments are `OperationValue`s. Mutually exclusive with the `local_cells` flag. /// diff --git a/turbopack/crates/turbo-tasks-macros/src/generic_type_macro.rs b/turbopack/crates/turbo-tasks-macros/src/generic_type_macro.rs index 334d7d81ee5e8..ad0677463895f 100644 --- a/turbopack/crates/turbo-tasks-macros/src/generic_type_macro.rs +++ b/turbopack/crates/turbo-tasks-macros/src/generic_type_macro.rs @@ -1,5 +1,6 @@ use proc_macro::TokenStream; use quote::quote; +use rustc_hash::FxHashSet; use syn::{parse_macro_input, spanned::Spanned, visit_mut::VisitMut, GenericParam, Lifetime, Type}; use turbo_tasks_macros_shared::{get_type_ident, GenericTypeInput}; @@ -105,7 +106,7 @@ pub fn generic_type(input: TokenStream) -> TokenStream { } struct ReplaceGenericsVisitor<'a> { - generics: &'a std::collections::HashSet, + generics: &'a FxHashSet, } impl VisitMut for ReplaceGenericsVisitor<'_> { @@ -134,7 +135,7 @@ fn replace_generics_with_unit<'a, P>(params: P, ty: &Type) -> Type where P: IntoIterator, { - let generics_set: std::collections::HashSet<_> = params + let generics_set: FxHashSet<_> = params .into_iter() .filter_map(|param| { if let GenericParam::Type(type_param) = param { diff --git a/turbopack/crates/turbo-tasks-memory/src/aggregation/tests.rs b/turbopack/crates/turbo-tasks-memory/src/aggregation/tests.rs index b9240e50ac1a7..bcfb2ac59cc55 100644 --- a/turbopack/crates/turbo-tasks-memory/src/aggregation/tests.rs +++ b/turbopack/crates/turbo-tasks-memory/src/aggregation/tests.rs @@ -1,5 +1,4 @@ use std::{ - collections::HashSet, fmt::Debug, hash::Hash, iter::once, @@ -15,6 +14,7 @@ use parking_lot::{Mutex, MutexGuard}; use rand::{rngs::SmallRng, Rng, SeedableRng}; use ref_cast::RefCast; use rstest::*; +use rustc_hash::FxHashSet; use turbo_tasks::FxIndexSet; use self::aggregation_data::prepare_aggregation_data; @@ -42,7 +42,7 @@ fn check_invariants(ctx: &NodeAggregationContext<'_>, node_ids: impl IntoIterato let mut queue = node_ids.into_iter().collect::>(); // print(ctx, &queue[0], true); #[allow(clippy::mutable_key_type, reason = "this is a test")] - let mut visited = HashSet::new(); + let mut visited = FxHashSet::default(); while let Some(node_id) = queue.pop() { assert_eq!(node_id.0.atomic.load(Ordering::SeqCst), 0); let node = ctx.node(&node_id); @@ -165,7 +165,7 @@ fn print_graph( name_fn: impl Fn(&C::NodeRef) -> String, ) { let mut queue = entries.into_iter().collect::>(); - let mut visited = queue.iter().cloned().collect::>(); + let mut visited = queue.iter().cloned().collect::>(); while let Some(node_id) = queue.pop() { let name = name_fn(&node_id); let node = ctx.node(&node_id); diff --git a/turbopack/crates/turbo-tasks-testing/src/lib.rs b/turbopack/crates/turbo-tasks-testing/src/lib.rs index a9a6aaedd0f10..f96dc5b2d016a 100644 --- a/turbopack/crates/turbo-tasks-testing/src/lib.rs +++ b/turbopack/crates/turbo-tasks-testing/src/lib.rs @@ -5,7 +5,6 @@ mod run; use std::{ borrow::Cow, - collections::HashMap, future::Future, mem::replace, panic::AssertUnwindSafe, @@ -14,6 +13,7 @@ use std::{ use anyhow::{anyhow, Result}; use futures::FutureExt; +use rustc_hash::FxHashMap; use turbo_tasks::{ backend::{CellContent, TaskCollectiblesMap, TypedCellContent}, event::{Event, EventListener}, @@ -34,7 +34,7 @@ enum Task { #[derive(Default)] pub struct VcStorage { this: Weak, - cells: Mutex>, + cells: Mutex>, tasks: Mutex>, } diff --git a/turbopack/crates/turbo-tasks-testing/tests/collectibles.rs b/turbopack/crates/turbo-tasks-testing/tests/collectibles.rs index 99ec9f6eeb0f1..fc43338986bcb 100644 --- a/turbopack/crates/turbo-tasks-testing/tests/collectibles.rs +++ b/turbopack/crates/turbo-tasks-testing/tests/collectibles.rs @@ -2,10 +2,11 @@ #![feature(arbitrary_self_types_pointers)] #![allow(clippy::needless_return)] // tokio macro-generated code doesn't respect this -use std::{collections::HashSet, time::Duration}; +use std::time::Duration; use anyhow::Result; use auto_hash_map::AutoSet; +use rustc_hash::FxHashSet; use tokio::time::sleep; use turbo_rcstr::RcStr; use turbo_tasks::{emit, CollectiblesSource, ResolvedVc, TryJoinIterExt, ValueToString, Vc}; @@ -20,7 +21,7 @@ async fn transitive_emitting() { let result_val = result_op.connect().strongly_consistent().await?; let list = result_op.peek_collectibles::>(); assert_eq!(list.len(), 2); - let mut expected = ["123", "42"].into_iter().collect::>(); + let mut expected = ["123", "42"].into_iter().collect::>(); for collectible in list { assert!(expected.remove(collectible.to_string().await?.as_str())) } @@ -38,7 +39,7 @@ async fn transitive_emitting_indirect() { let collectibles_op = my_transitive_emitting_function_collectibles("".into(), "".into()); let list = collectibles_op.connect().strongly_consistent().await?; assert_eq!(list.len(), 2); - let mut expected = ["123", "42"].into_iter().collect::>(); + let mut expected = ["123", "42"].into_iter().collect::>(); for collectible in list.iter() { assert!(expected.remove(collectible.to_string().await?.as_str())) } @@ -56,7 +57,7 @@ async fn multi_emitting() { let result_val = result_op.connect().strongly_consistent().await?; let list = result_op.peek_collectibles::>(); assert_eq!(list.len(), 2); - let mut expected = ["123", "42"].into_iter().collect::>(); + let mut expected = ["123", "42"].into_iter().collect::>(); for collectible in list { assert!(expected.remove(collectible.to_string().await?.as_str())) } diff --git a/turbopack/crates/turbo-tasks/src/debug/mod.rs b/turbopack/crates/turbo-tasks/src/debug/mod.rs index b058ce2e49405..cb6d59f240a57 100644 --- a/turbopack/crates/turbo-tasks/src/debug/mod.rs +++ b/turbopack/crates/turbo-tasks/src/debug/mod.rs @@ -188,7 +188,7 @@ where } } -impl ValueDebugFormat for std::collections::HashMap +impl ValueDebugFormat for std::collections::HashMap where K: Debug, V: ValueDebugFormat, diff --git a/turbopack/crates/turbo-tasks/src/effect.rs b/turbopack/crates/turbo-tasks/src/effect.rs index 2ac7eb66be80e..846a44d9e1f8c 100644 --- a/turbopack/crates/turbo-tasks/src/effect.rs +++ b/turbopack/crates/turbo-tasks/src/effect.rs @@ -1,8 +1,9 @@ -use std::{borrow::Cow, collections::HashSet, future::Future, mem::replace, panic, pin::Pin}; +use std::{borrow::Cow, future::Future, mem::replace, panic, pin::Pin}; use anyhow::{anyhow, Result}; use auto_hash_map::AutoSet; use parking_lot::Mutex; +use rustc_hash::FxHashSet; use tracing::{Instrument, Span}; use crate::{ @@ -233,7 +234,7 @@ impl PartialEq for Effects { .effects .iter() .map(ReadRef::ptr) - .collect::>(); + .collect::>(); other .effects .iter() diff --git a/turbopack/crates/turbo-tasks/src/graph/adjacency_map.rs b/turbopack/crates/turbo-tasks/src/graph/adjacency_map.rs index 5acd4358e903d..387544a3ac651 100644 --- a/turbopack/crates/turbo-tasks/src/graph/adjacency_map.rs +++ b/turbopack/crates/turbo-tasks/src/graph/adjacency_map.rs @@ -1,7 +1,4 @@ -use std::{ - collections::{HashSet, VecDeque}, - hash::Hash, -}; +use std::{collections::VecDeque, hash::Hash}; use rustc_hash::{FxHashMap, FxHashSet}; use serde::{Deserialize, Serialize}; @@ -102,7 +99,7 @@ where .rev() .map(|root| (ReverseTopologicalPass::Pre, root)) .collect(), - visited: HashSet::new(), + visited: FxHashSet::default(), } } @@ -164,7 +161,7 @@ where { adjacency_map: FxHashMap>, stack: Vec<(ReverseTopologicalPass, T)>, - visited: HashSet, + visited: FxHashSet, } impl Iterator for IntoReverseTopologicalIter diff --git a/turbopack/crates/turbo-tasks/src/graph/graph_store.rs b/turbopack/crates/turbo-tasks/src/graph/graph_store.rs index abdec7122a165..f6ec1b50c7fda 100644 --- a/turbopack/crates/turbo-tasks/src/graph/graph_store.rs +++ b/turbopack/crates/turbo-tasks/src/graph/graph_store.rs @@ -1,4 +1,6 @@ -use std::{collections::HashSet, hash::Hash}; +use std::hash::Hash; + +use rustc_hash::FxHashSet; use super::VisitedNodes; @@ -53,7 +55,7 @@ where StoreImpl: GraphStore, { store: StoreImpl, - visited: HashSet, + visited: FxHashSet, } impl SkipDuplicates @@ -63,11 +65,11 @@ where pub fn new(store: StoreImpl) -> Self { Self { store, - visited: Default::default(), + visited: FxHashSet::default(), } } - pub fn new_with_visited_nodes(store: StoreImpl, visited: HashSet) -> Self { + pub fn new_with_visited_nodes(store: StoreImpl, visited: FxHashSet) -> Self { Self { store, visited } } } diff --git a/turbopack/crates/turbo-tasks/src/graph/graph_traversal.rs b/turbopack/crates/turbo-tasks/src/graph/graph_traversal.rs index 42b560f455c95..52c6f3b288819 100644 --- a/turbopack/crates/turbo-tasks/src/graph/graph_traversal.rs +++ b/turbopack/crates/turbo-tasks/src/graph/graph_traversal.rs @@ -1,7 +1,8 @@ -use std::{collections::HashSet, future::Future}; +use std::future::Future; use anyhow::Result; use futures::{stream::FuturesUnordered, StreamExt}; +use rustc_hash::FxHashSet; use super::{ graph_store::{GraphNode, GraphStore}, @@ -11,7 +12,7 @@ use super::{ /// A list of modules that were already visited and should be skipped (including their subgraphs). #[derive(Clone, Default, Debug)] -pub struct VisitedNodes(pub HashSet); +pub struct VisitedNodes(pub FxHashSet); /// [`GraphTraversal`] is a utility type that can be used to traverse a graph of /// nodes, where each node can have a variable number of outgoing edges. diff --git a/turbopack/crates/turbopack-bench/Cargo.toml b/turbopack/crates/turbopack-bench/Cargo.toml index 3646b0bba790e..3465c1569ee52 100644 --- a/turbopack/crates/turbopack-bench/Cargo.toml +++ b/turbopack/crates/turbopack-bench/Cargo.toml @@ -29,6 +29,7 @@ parking_lot = { workspace = true } portpicker = "0.1.1" rand = { workspace = true } regex = { workspace = true } +rustc-hash = { workspace = true } serde_json = { workspace = true } tempfile = { workspace = true } tokio = { workspace = true, features = ["full"] } diff --git a/turbopack/crates/turbopack-bench/src/util/module_picker.rs b/turbopack/crates/turbopack-bench/src/util/module_picker.rs index faaa1014026fa..af0b5ea23724e 100644 --- a/turbopack/crates/turbopack-bench/src/util/module_picker.rs +++ b/turbopack/crates/turbopack-bench/src/util/module_picker.rs @@ -1,6 +1,7 @@ -use std::{collections::HashMap, path::PathBuf}; +use std::path::PathBuf; use rand::{rngs::StdRng, seq::SliceRandom, SeedableRng}; +use rustc_hash::FxHashMap; /// Picks modules at random, but with a fixed seed so runs are somewhat /// reproducible. @@ -9,7 +10,7 @@ use rand::{rngs::StdRng, seq::SliceRandom, SeedableRng}; /// the same sequence in different samples. pub struct ModulePicker { depths: Vec, - modules_by_depth: HashMap>, + modules_by_depth: FxHashMap>, rng: parking_lot::Mutex, } @@ -21,7 +22,7 @@ impl ModulePicker { // Ensure the module order is deterministic. modules.sort(); - let mut modules_by_depth: HashMap<_, Vec<_>> = HashMap::new(); + let mut modules_by_depth: FxHashMap<_, Vec<_>> = FxHashMap::default(); for (module, depth) in modules { modules_by_depth.entry(depth).or_default().push(module); } diff --git a/turbopack/crates/turbopack-cli-utils/Cargo.toml b/turbopack/crates/turbopack-cli-utils/Cargo.toml index 079f6d851f8de..1dc9decf1b093 100644 --- a/turbopack/crates/turbopack-cli-utils/Cargo.toml +++ b/turbopack/crates/turbopack-cli-utils/Cargo.toml @@ -19,6 +19,7 @@ anyhow = { workspace = true } clap = { workspace = true, features = ["derive"] } crossterm = "0.26.0" owo-colors = { workspace = true } +rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"] } turbo-tasks = { workspace = true } turbo-tasks-fs = { workspace = true } diff --git a/turbopack/crates/turbopack-cli-utils/src/issue.rs b/turbopack/crates/turbopack-cli-utils/src/issue.rs index 6aa2de385796c..ec61321bca4e4 100644 --- a/turbopack/crates/turbopack-cli-utils/src/issue.rs +++ b/turbopack/crates/turbopack-cli-utils/src/issue.rs @@ -1,7 +1,7 @@ use std::{ borrow::Cow, cmp::min, - collections::{hash_map::Entry, HashMap, HashSet}, + collections::hash_map::Entry, fmt::Write as _, path::{Path, PathBuf}, str::FromStr, @@ -11,6 +11,7 @@ use std::{ use anyhow::{anyhow, Result}; use crossterm::style::{StyledContent, Stylize}; use owo_colors::{OwoColorize as _, Style}; +use rustc_hash::{FxHashMap, FxHashSet}; use turbo_tasks::{RawVc, ReadRef, TransientInstance, TransientValue, TryJoinIterExt, Vc}; use turbo_tasks_fs::{source_context::get_source_context, FileLinesContent}; use turbopack_core::issue::{ @@ -186,7 +187,8 @@ pub fn format_issue( issue_text } -pub type GroupedIssues = HashMap>>>; +pub type GroupedIssues = + FxHashMap>>>; const DEFAULT_SHOW_COUNT: usize = 3; @@ -231,13 +233,13 @@ pub struct LogOptions { struct SeenIssues { /// Keeps track of all issue pulled from the source. Used so that we can /// decrement issues that are not pulled in the current synchronization. - source_to_issue_ids: HashMap>, + source_to_issue_ids: FxHashMap>, /// Counts the number of times a particular issue is seen across all /// sources. As long as the count is positive, an issue is considered /// "seen" and will not be relogged. Once the count reaches zero, the /// issue is removed and the next time its seen it will be considered new. - issues_count: HashMap, + issues_count: FxHashMap, } impl SeenIssues { @@ -247,7 +249,7 @@ impl SeenIssues { /// Synchronizes state between the issues previously pulled from this /// source, to the issues now pulled. - fn new_ids(&mut self, source: RawVc, issue_ids: HashSet) -> HashSet { + fn new_ids(&mut self, source: RawVc, issue_ids: FxHashSet) -> FxHashSet { let old = self.source_to_issue_ids.entry(source).or_default(); // difference is the issues that were never counted before. @@ -274,7 +276,7 @@ impl SeenIssues { } }) .cloned() - .collect::>(); + .collect::>(); // Old now contains only the ids that were not present in the new issue_ids. for id in old.iter() { @@ -350,7 +352,7 @@ impl IssueReporter for ConsoleUi { log_level, .. } = self.options; - let mut grouped_issues: GroupedIssues = HashMap::new(); + let mut grouped_issues: GroupedIssues = FxHashMap::default(); let issues = issues .iter_with_shortest_path() @@ -362,7 +364,7 @@ impl IssueReporter for ConsoleUi { .try_join() .await?; - let issue_ids = issues.iter().map(|(_, id)| *id).collect::>(); + let issue_ids = issues.iter().map(|(_, id)| *id).collect::>(); let mut new_ids = self .seen .lock() diff --git a/turbopack/crates/turbopack-cli/Cargo.toml b/turbopack/crates/turbopack-cli/Cargo.toml index 6b1aa163e7dfa..3512834adf5cd 100644 --- a/turbopack/crates/turbopack-cli/Cargo.toml +++ b/turbopack/crates/turbopack-cli/Cargo.toml @@ -40,8 +40,10 @@ dunce = { workspace = true } futures = { workspace = true } mime = { workspace = true } owo-colors = { workspace = true } +rustc-hash = { workspace = true } serde = { workspace = true } tokio = { workspace = true, features = ["full"] } +tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter", "json"] } turbo-rcstr = { workspace = true } turbo-tasks = { workspace = true } @@ -54,7 +56,6 @@ turbopack = { workspace = true } turbopack-browser = { workspace = true } turbopack-cli-utils = { workspace = true } turbopack-core = { workspace = true } -tracing = { workspace = true } turbopack-dev-server = { workspace = true } turbopack-ecmascript-plugins = { workspace = true, features = [ "transform_emotion", diff --git a/turbopack/crates/turbopack-cli/src/build/mod.rs b/turbopack/crates/turbopack-cli/src/build/mod.rs index 7aea06aecc895..54f8398d48c55 100644 --- a/turbopack/crates/turbopack-cli/src/build/mod.rs +++ b/turbopack/crates/turbopack-cli/src/build/mod.rs @@ -1,5 +1,4 @@ use std::{ - collections::HashSet, env::current_dir, mem::forget, path::{PathBuf, MAIN_SEPARATOR}, @@ -7,6 +6,7 @@ use std::{ }; use anyhow::{bail, Context, Result}; +use rustc_hash::FxHashSet; use turbo_rcstr::RcStr; use turbo_tasks::{ apply_effects, ReadConsistency, ResolvedVc, TransientInstance, TryJoinIterExt, TurboTasks, @@ -438,7 +438,7 @@ async fn build_internal( .try_join() .await?; - let mut chunks: HashSet>> = HashSet::new(); + let mut chunks: FxHashSet>> = FxHashSet::default(); for chunk_group in entry_chunk_groups { chunks.extend(&*all_assets_from_entries(*chunk_group).await?); } diff --git a/turbopack/crates/turbopack-cli/src/dev/mod.rs b/turbopack/crates/turbopack-cli/src/dev/mod.rs index e2760aff13f97..2749eaaba2133 100644 --- a/turbopack/crates/turbopack-cli/src/dev/mod.rs +++ b/turbopack/crates/turbopack-cli/src/dev/mod.rs @@ -1,5 +1,4 @@ use std::{ - collections::HashSet, env::current_dir, future::{join, Future}, io::{stdout, Write}, @@ -11,6 +10,7 @@ use std::{ use anyhow::{Context, Result}; use owo_colors::OwoColorize; +use rustc_hash::FxHashSet; use turbo_rcstr::RcStr; use turbo_tasks::{ util::{FormatBytes, FormatDuration}, @@ -331,7 +331,7 @@ async fn source( .await?; let introspect = ResolvedVc::upcast( IntrospectionSource { - roots: HashSet::from([ResolvedVc::upcast(main_source)]), + roots: FxHashSet::from_iter([ResolvedVc::upcast(main_source)]), } .resolved_cell(), ); diff --git a/turbopack/crates/turbopack-core/src/module_graph/chunk_group_info.rs b/turbopack/crates/turbopack-core/src/module_graph/chunk_group_info.rs index fb69cfe694cbb..97de6bb0f07d2 100644 --- a/turbopack/crates/turbopack-core/src/module_graph/chunk_group_info.rs +++ b/turbopack/crates/turbopack-core/src/module_graph/chunk_group_info.rs @@ -1,5 +1,5 @@ use std::{ - collections::{hash_map::Entry, BinaryHeap, HashMap, HashSet}, + collections::{hash_map::Entry, BinaryHeap}, hash::Hash, ops::{Deref, DerefMut}, }; @@ -8,6 +8,7 @@ use anyhow::Result; use either::Either; use petgraph::graph::{DiGraph, EdgeIndex, NodeIndex}; use roaring::RoaringBitmap; +use rustc_hash::{FxHashMap, FxHashSet}; use serde::{Deserialize, Serialize}; use tracing::Instrument; use turbo_rcstr::RcStr; @@ -76,7 +77,7 @@ impl Hash for RoaringBitmapWrapper { } #[turbo_tasks::value(transparent)] -pub struct ChunkGroupInfo(HashMap>, RoaringBitmapWrapper>); +pub struct ChunkGroupInfo(FxHashMap>, RoaringBitmapWrapper>); #[derive(Debug, Clone, PartialEq, Eq, Hash)] enum ChunkGroup { @@ -164,18 +165,18 @@ pub async fn compute_chunk_group_info(graph: &ModuleGraph) -> Result = HashMap::new(); - let mut chunk_groups_from_id: HashMap = HashMap::new(); + let mut chunk_groups_to_id: FxHashMap = FxHashMap::default(); + let mut chunk_groups_from_id: FxHashMap = FxHashMap::default(); - let mut module_chunk_groups: HashMap>, RoaringBitmapWrapper> = - HashMap::new(); + let mut module_chunk_groups: FxHashMap>, RoaringBitmapWrapper> = + FxHashMap::default(); let graphs = graph.graphs.iter().try_join().await?; let module_count = graphs.iter().map(|g| g.graph.node_count()).sum::(); span.record("module_count", module_count); // First, compute the depth for each module in the graph - let mut module_depth: HashMap>, usize> = HashMap::new(); + let mut module_depth: FxHashMap>, usize> = FxHashMap::default(); // use all entries from all graphs let entries = graphs .iter() @@ -202,7 +203,7 @@ pub async fn compute_chunk_group_info(graph: &ModuleGraph) -> Result, node: &'_ SingleModuleGraphModuleNode, - module_chunk_groups: &mut HashMap< + module_chunk_groups: &mut FxHashMap< ResolvedVc>, RoaringBitmapWrapper, >| @@ -316,7 +317,7 @@ pub async fn compute_chunk_group_info(graph: &ModuleGraph) -> Result>(); + .collect::>(); self.affecting_sources.extend( other .affecting_sources @@ -639,7 +640,7 @@ impl ResolveResult { .affecting_sources .iter() .copied() - .collect::>(); + .collect::>(); self.affecting_sources.extend( other .affecting_sources @@ -2795,7 +2796,7 @@ async fn handle_exports_imports_field( query: Vc, ) -> Result> { let mut results = Vec::new(); - let mut conditions_state = HashMap::new(); + let mut conditions_state = FxHashMap::default(); let query_str = query.await?; let req = Pattern::Constant(format!("{}{}", path, query_str).into()); diff --git a/turbopack/crates/turbopack-core/src/resolve/plugin.rs b/turbopack/crates/turbopack-core/src/resolve/plugin.rs index 17ed289ce1187..a70d0aba0f7b7 100644 --- a/turbopack/crates/turbopack-core/src/resolve/plugin.rs +++ b/turbopack/crates/turbopack-core/src/resolve/plugin.rs @@ -1,6 +1,5 @@ -use std::collections::HashSet; - use anyhow::Result; +use rustc_hash::FxHashSet; use turbo_rcstr::RcStr; use turbo_tasks::{ResolvedVc, Value, Vc}; use turbo_tasks_fs::{glob::Glob, FileSystemPath}; @@ -45,7 +44,7 @@ impl AfterResolvePluginCondition { #[turbo_tasks::value] pub enum BeforeResolvePluginCondition { Request(ResolvedVc), - Modules(HashSet), + Modules(FxHashSet), } #[turbo_tasks::value_impl] diff --git a/turbopack/crates/turbopack-core/src/resolve/remap.rs b/turbopack/crates/turbopack-core/src/resolve/remap.rs index eb6fc9a1edfe3..b042c19788e49 100644 --- a/turbopack/crates/turbopack-core/src/resolve/remap.rs +++ b/turbopack/crates/turbopack-core/src/resolve/remap.rs @@ -1,10 +1,7 @@ -use std::{ - collections::{BTreeMap, HashMap}, - fmt::Display, - ops::Deref, -}; +use std::{collections::BTreeMap, fmt::Display, ops::Deref}; use anyhow::{bail, Result}; +use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use serde_json::Value; use turbo_rcstr::RcStr; @@ -127,7 +124,7 @@ impl SubpathValue { &'a self, conditions: &BTreeMap, unspecified_condition: &ConditionValue, - condition_overrides: &mut HashMap<&'a str, ConditionValue>, + condition_overrides: &mut FxHashMap<&'a str, ConditionValue>, target: &mut Vec<(&'a str, Vec<(&'a str, bool)>)>, ) -> bool { match self { @@ -242,7 +239,7 @@ impl ReplacedSubpathValue { &'a self, conditions: &BTreeMap, unspecified_condition: &ConditionValue, - condition_overrides: &mut HashMap<&'a str, ConditionValue>, + condition_overrides: &mut FxHashMap<&'a str, ConditionValue>, target: &mut Vec<(&'a Pattern, Vec<(&'a str, bool)>)>, ) -> bool { match self { diff --git a/turbopack/crates/turbopack-css/Cargo.toml b/turbopack/crates/turbopack-css/Cargo.toml index 33582156f6403..b705b40ccdde3 100644 --- a/turbopack/crates/turbopack-css/Cargo.toml +++ b/turbopack/crates/turbopack-css/Cargo.toml @@ -19,10 +19,16 @@ indoc = { workspace = true } lightningcss = { workspace = true } once_cell = { workspace = true } parcel_selectors = { workspace = true } +parcel_sourcemap = "2.1.1" regex = { workspace = true } +rustc-hash = { workspace = true } serde = { workspace = true } -urlencoding = { workspace = true } - +smallvec = { workspace = true } +swc_core = { workspace = true, features = [ + "ecma_ast", + "common", + "common_concurrent", +] } tracing = { workspace = true } turbo-rcstr = { workspace = true } turbo-tasks = { workspace = true } @@ -31,14 +37,7 @@ turbo-tasks-hash = { workspace = true } turbopack-core = { workspace = true } turbopack-ecmascript = { workspace = true } turbopack-swc-utils = { workspace = true } - -parcel_sourcemap = "2.1.1" -smallvec = { workspace = true } -swc_core = { workspace = true, features = [ - "ecma_ast", - "common", - "common_concurrent", -] } +urlencoding = { workspace = true } [build-dependencies] turbo-tasks-build = { workspace = true } diff --git a/turbopack/crates/turbopack-css/src/process.rs b/turbopack/crates/turbopack-css/src/process.rs index 0e13f56601267..0c053b729b845 100644 --- a/turbopack/crates/turbopack-css/src/process.rs +++ b/turbopack/crates/turbopack-css/src/process.rs @@ -1,7 +1,4 @@ -use std::{ - collections::HashMap, - sync::{Arc, RwLock}, -}; +use std::sync::{Arc, RwLock}; use anyhow::{bail, Result}; use lightningcss::{ @@ -12,6 +9,7 @@ use lightningcss::{ visit_types, visitor::Visit, }; +use rustc_hash::FxHashMap; use smallvec::smallvec; use swc_core::{ base::sourcemap::SourceMapBuilder, @@ -148,7 +146,7 @@ pub enum CssWithPlaceholderResult { exports: Option>, #[turbo_tasks(trace_ignore)] - placeholders: HashMap>, + placeholders: FxHashMap>, }, Unparseable, NotFound, @@ -210,7 +208,7 @@ pub async fn process_css_with_placeholder( exports, references: *references, url_references: *url_references, - placeholders: HashMap::new(), + placeholders: FxHashMap::default(), } .cell()) } @@ -246,7 +244,7 @@ pub async fn finalize_css( let url_references = *url_references; - let mut url_map = HashMap::new(); + let mut url_map = FxHashMap::default(); for (src, reference) in (*url_references.await?).iter() { let resolved = diff --git a/turbopack/crates/turbopack-css/src/references/url.rs b/turbopack/crates/turbopack-css/src/references/url.rs index 00fa0e6053d9b..d7d7df8fe6792 100644 --- a/turbopack/crates/turbopack-css/src/references/url.rs +++ b/turbopack/crates/turbopack-css/src/references/url.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, convert::Infallible}; +use std::convert::Infallible; use anyhow::{bail, Result}; use lightningcss::{ @@ -6,6 +6,7 @@ use lightningcss::{ visit_types, visitor::{Visit, Visitor}, }; +use rustc_hash::FxHashMap; use turbo_rcstr::RcStr; use turbo_tasks::{debug::ValueDebug, ResolvedVc, Value, ValueToString, Vc}; use turbopack_core::{ @@ -148,14 +149,14 @@ pub async fn resolve_url_reference( pub fn replace_url_references( ss: &mut StyleSheetLike<'static, 'static>, - urls: &HashMap, + urls: &FxHashMap, ) { let mut replacer = AssetReferenceReplacer { urls }; ss.0.visit(&mut replacer).unwrap(); } struct AssetReferenceReplacer<'a> { - urls: &'a HashMap, + urls: &'a FxHashMap, } impl Visitor<'_> for AssetReferenceReplacer<'_> { diff --git a/turbopack/crates/turbopack-dev-server/Cargo.toml b/turbopack/crates/turbopack-dev-server/Cargo.toml index 19448e34e11f6..94f229142907a 100644 --- a/turbopack/crates/turbopack-dev-server/Cargo.toml +++ b/turbopack/crates/turbopack-dev-server/Cargo.toml @@ -27,6 +27,7 @@ mime = { workspace = true } mime_guess = "2.0.4" parking_lot = { workspace = true } pin-project-lite = { workspace = true } +rustc-hash = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } serde_qs = { workspace = true } @@ -35,18 +36,17 @@ tokio = { workspace = true } tokio-stream = "0.1.9" tokio-util = { workspace = true } tracing = { workspace = true } -urlencoding = "2.1.2" - turbo-rcstr = { workspace = true } turbo-tasks = { workspace = true } turbo-tasks-bytes = { workspace = true } turbo-tasks-fs = { workspace = true } turbo-tasks-hash = { workspace = true } +# TODO remove this dependency +turbopack-cli-utils = { workspace = true } turbopack-core = { workspace = true } turbopack-ecmascript = { workspace = true } turbopack-ecmascript-hmr-protocol = { workspace = true } -# TODO remove this dependency -turbopack-cli-utils = { workspace = true } +urlencoding = "2.1.2" [build-dependencies] turbo-tasks-build = { workspace = true } diff --git a/turbopack/crates/turbopack-dev-server/src/introspect/mod.rs b/turbopack/crates/turbopack-dev-server/src/introspect/mod.rs index ba3a7a489330a..faad9c0928a14 100644 --- a/turbopack/crates/turbopack-dev-server/src/introspect/mod.rs +++ b/turbopack/crates/turbopack-dev-server/src/introspect/mod.rs @@ -1,6 +1,7 @@ -use std::{borrow::Cow, collections::HashSet, fmt::Display}; +use std::{borrow::Cow, fmt::Display}; use anyhow::Result; +use rustc_hash::FxHashSet; use turbo_rcstr::RcStr; use turbo_tasks::{ReadRef, ResolvedVc, TryJoinIterExt, Vc}; use turbo_tasks_fs::{json::parse_json_with_source_context, File}; @@ -18,7 +19,7 @@ use crate::source::{ #[turbo_tasks::value(shared)] pub struct IntrospectionSource { - pub roots: HashSet>>, + pub roots: FxHashSet>>, } #[turbo_tasks::value_impl] diff --git a/turbopack/crates/turbopack-dev-server/src/source/asset_graph.rs b/turbopack/crates/turbopack-dev-server/src/source/asset_graph.rs index fb2020d7418fe..9270e35533102 100644 --- a/turbopack/crates/turbopack-dev-server/src/source/asset_graph.rs +++ b/turbopack/crates/turbopack-dev-server/src/source/asset_graph.rs @@ -1,9 +1,7 @@ -use std::{ - collections::{HashSet, VecDeque}, - iter::once, -}; +use std::{collections::VecDeque, iter::once}; use anyhow::Result; +use rustc_hash::FxHashSet; use turbo_rcstr::RcStr; use turbo_tasks::{ fxindexset, Completion, FxIndexMap, FxIndexSet, ResolvedVc, State, TryJoinIterExt, Value, @@ -25,7 +23,7 @@ use super::{ #[turbo_tasks::value(transparent)] struct OutputAssetsMap(FxIndexMap>>); -type ExpandedState = State>; +type ExpandedState = State>; #[turbo_tasks::value(serialization = "none", eq = "manual", cell = "new")] pub struct AssetGraphContentSource { @@ -59,7 +57,7 @@ impl AssetGraphContentSource { Self::cell(AssetGraphContentSource { root_path, root_assets: ResolvedVc::cell(fxindexset! { root_asset }), - expanded: Some(State::new(HashSet::new())), + expanded: Some(State::new(FxHashSet::default())), }) } @@ -86,7 +84,7 @@ impl AssetGraphContentSource { Self::cell(AssetGraphContentSource { root_path, root_assets, - expanded: Some(State::new(HashSet::new())), + expanded: Some(State::new(FxHashSet::default())), }) } @@ -111,7 +109,7 @@ async fn expand( let mut map = FxIndexMap::default(); let mut assets = Vec::new(); let mut queue = VecDeque::with_capacity(32); - let mut assets_set = HashSet::new(); + let mut assets_set = FxHashSet::default(); let root_assets_with_path = root_assets .iter() .map(|&asset| async move { diff --git a/turbopack/crates/turbopack-ecmascript/src/analyzer/imports.rs b/turbopack/crates/turbopack-ecmascript/src/analyzer/imports.rs index 80fdf5af91795..94a4130f25465 100644 --- a/turbopack/crates/turbopack-ecmascript/src/analyzer/imports.rs +++ b/turbopack/crates/turbopack-ecmascript/src/analyzer/imports.rs @@ -1,10 +1,7 @@ -use std::{ - collections::{BTreeMap, HashMap}, - fmt::Display, -}; +use std::{collections::BTreeMap, fmt::Display}; use once_cell::sync::Lazy; -use rustc_hash::FxHashSet; +use rustc_hash::{FxHashMap, FxHashSet}; use swc_core::{ common::{comments::Comments, source_map::SmallPos, BytePos, Span, Spanned}, ecma::{ @@ -176,7 +173,7 @@ pub(crate) struct ImportMap { /// full details. /// /// [magic]: https://webpack.js.org/api/module-methods/#magic-comments - attributes: HashMap, + attributes: FxHashMap, /// The module specifiers of star imports that are accessed dynamically and should be imported /// as a whole. diff --git a/turbopack/crates/turbopack-ecmascript/src/analyzer/linker.rs b/turbopack/crates/turbopack-ecmascript/src/analyzer/linker.rs index 54a6866e5e8c9..3f770a2f26f6d 100644 --- a/turbopack/crates/turbopack-ecmascript/src/analyzer/linker.rs +++ b/turbopack/crates/turbopack-ecmascript/src/analyzer/linker.rs @@ -1,11 +1,7 @@ -use std::{ - collections::{hash_map::Entry, HashSet}, - future::Future, - mem::take, -}; +use std::{collections::hash_map::Entry, future::Future, mem::take}; use anyhow::Result; -use rustc_hash::FxHashMap; +use rustc_hash::{FxHashMap, FxHashSet}; use swc_core::ecma::ast::Id; use super::{graph::VarGraph, JsValue}; @@ -60,7 +56,7 @@ where let mut done: Vec = Vec::new(); // Tracks the number of nodes in the queue and done combined let mut total_nodes = 0; - let mut cycle_stack: HashSet = HashSet::new(); + let mut cycle_stack: FxHashSet = FxHashSet::default(); // Tracks the number linking steps so far let mut steps = 0; diff --git a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs index 7036f735b2c9c..33c02f96cc4be 100644 --- a/turbopack/crates/turbopack-ecmascript/src/references/mod.rs +++ b/turbopack/crates/turbopack-ecmascript/src/references/mod.rs @@ -17,12 +17,7 @@ pub mod unreachable; pub mod util; pub mod worker; -use std::{ - borrow::Cow, - collections::{BTreeMap, HashMap}, - mem::take, - sync::Arc, -}; +use std::{borrow::Cow, collections::BTreeMap, mem::take, sync::Arc}; use anyhow::{bail, Result}; use constant_condition::{ConstantCondition, ConstantConditionValue}; @@ -2937,7 +2932,7 @@ enum StaticExpr { // TODO get rid of that #[derive(Default)] struct StaticAnalyser { - imports: HashMap)>, + imports: FxHashMap)>, } impl StaticAnalyser { diff --git a/turbopack/crates/turbopack-ecmascript/src/swc_comments.rs b/turbopack/crates/turbopack-ecmascript/src/swc_comments.rs index a02892f7e0b28..c4f7a683ce1f4 100644 --- a/turbopack/crates/turbopack-ecmascript/src/swc_comments.rs +++ b/turbopack/crates/turbopack-ecmascript/src/swc_comments.rs @@ -1,5 +1,6 @@ -use std::{cell::RefCell, collections::HashMap, mem::take}; +use std::{cell::RefCell, mem::take}; +use rustc_hash::FxHashMap; use swc_core::{ base::SwcComments, common::{ @@ -12,8 +13,8 @@ use swc_core::{ /// variants are still implemented, but do not mutate the content. They are used /// by the SWC Emitter. pub struct ImmutableComments { - pub leading: HashMap>, - pub trailing: HashMap>, + pub leading: FxHashMap>, + pub trailing: FxHashMap>, } impl ImmutableComments { @@ -185,8 +186,8 @@ impl Comments for ImmutableComments { } pub struct CowComments<'a> { - leading: RefCell>>, - trailing: RefCell>>, + leading: RefCell>>, + trailing: RefCell>>, } impl<'a> CowComments<'a> { diff --git a/turbopack/crates/turbopack-image/Cargo.toml b/turbopack/crates/turbopack-image/Cargo.toml index 98e775f7225c8..d0016292eb5d1 100644 --- a/turbopack/crates/turbopack-image/Cargo.toml +++ b/turbopack/crates/turbopack-image/Cargo.toml @@ -32,6 +32,7 @@ image = { workspace = true, default-features = false, features = [ mime = { workspace = true } once_cell = { workspace = true } regex = { workspace = true } +rustc-hash = { workspace = true } serde = { workspace = true } serde_with = { workspace = true } turbo-tasks = { workspace = true } diff --git a/turbopack/crates/turbopack-image/src/process/svg.rs b/turbopack/crates/turbopack-image/src/process/svg.rs index 59956bbbc0715..e6b30af644f63 100644 --- a/turbopack/crates/turbopack-image/src/process/svg.rs +++ b/turbopack/crates/turbopack-image/src/process/svg.rs @@ -1,15 +1,14 @@ // Ported from https://github.com/image-size/image-size/blob/94e9c1ee913b71222d7583dc904ac0116ae00834/lib/types/svg.ts // see SVG_LICENSE for license info -use std::collections::HashMap; - use anyhow::{anyhow, bail, Result}; use once_cell::sync::Lazy; use regex::Regex; +use rustc_hash::FxHashMap; const INCH_CM: f64 = 2.54; -static UNITS: Lazy> = Lazy::new(|| { - HashMap::from([ +static UNITS: Lazy> = Lazy::new(|| { + FxHashMap::from_iter([ ("in", 96.0), ("cm", 96.0 / INCH_CM), ("em", 16.0), diff --git a/turbopack/crates/turbopack-node/Cargo.toml b/turbopack/crates/turbopack-node/Cargo.toml index d60575d01ea99..b82ca1bade9cc 100644 --- a/turbopack/crates/turbopack-node/Cargo.toml +++ b/turbopack/crates/turbopack-node/Cargo.toml @@ -31,6 +31,7 @@ once_cell = { workspace = true } owo-colors = { workspace = true } parking_lot = { workspace = true } regex = { workspace = true } +rustc-hash = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } serde_with = { workspace = true, features = ["base64"] } diff --git a/turbopack/crates/turbopack-node/src/lib.rs b/turbopack/crates/turbopack-node/src/lib.rs index e90a187a62ef2..282f97215bfd6 100644 --- a/turbopack/crates/turbopack-node/src/lib.rs +++ b/turbopack/crates/turbopack-node/src/lib.rs @@ -4,10 +4,11 @@ #![feature(arbitrary_self_types_pointers)] #![feature(extract_if)] -use std::{collections::HashMap, iter::once, thread::available_parallelism}; +use std::{iter::once, thread::available_parallelism}; use anyhow::{bail, Result}; pub use node_entry::{NodeEntry, NodeRenderingEntries, NodeRenderingEntry}; +use rustc_hash::FxHashMap; use turbo_rcstr::RcStr; use turbo_tasks::{ graph::{AdjacencyMap, GraphTraversal}, @@ -80,7 +81,7 @@ async fn internal_assets( } #[turbo_tasks::value(transparent)] -pub struct AssetsForSourceMapping(HashMap>>); +pub struct AssetsForSourceMapping(FxHashMap>>); /// Extracts a map of "internal" assets ([`internal_assets`]) which implement /// the [GenerateSourceMap] trait. @@ -91,7 +92,7 @@ async fn internal_assets_for_source_mapping( ) -> Result> { let internal_assets = internal_assets(intermediate_asset, intermediate_output_path).await?; let intermediate_output_path = &*intermediate_output_path.await?; - let mut internal_assets_for_source_mapping = HashMap::new(); + let mut internal_assets_for_source_mapping = FxHashMap::default(); for asset in internal_assets.iter() { if let Some(generate_source_map) = ResolvedVc::try_sidecast::>(*asset) diff --git a/turbopack/crates/turbopack-node/src/pool.rs b/turbopack/crates/turbopack-node/src/pool.rs index be3585a46df51..7b876ebaf5091 100644 --- a/turbopack/crates/turbopack-node/src/pool.rs +++ b/turbopack/crates/turbopack-node/src/pool.rs @@ -1,7 +1,6 @@ use std::{ borrow::Cow, cmp::max, - collections::HashMap, fmt::{Debug, Display}, future::Future, mem::take, @@ -15,6 +14,7 @@ use anyhow::{bail, Context, Result}; use futures::join; use owo_colors::{OwoColorize, Style}; use parking_lot::Mutex; +use rustc_hash::FxHashMap; use serde::{de::DeserializeOwned, Serialize}; use tokio::{ io::{ @@ -203,7 +203,7 @@ impl OutputStreamHandler { } let mut buffer = Vec::new(); - let mut own_output = HashMap::new(); + let mut own_output = FxHashMap::default(); let mut nesting: u32 = 0; let mut in_stack = None; let mut stack_trace_buffer = Vec::new(); @@ -309,7 +309,7 @@ impl OutputStreamHandler { impl NodeJsPoolProcess { async fn new( cwd: &Path, - env: &HashMap, + env: &FxHashMap, entrypoint: &Path, assets_for_source_mapping: ResolvedVc, assets_root: ResolvedVc, @@ -688,7 +688,7 @@ enum AcquiredPermits { pub struct NodeJsPool { cwd: PathBuf, entrypoint: PathBuf, - env: HashMap, + env: FxHashMap, pub assets_for_source_mapping: ResolvedVc, pub assets_root: ResolvedVc, pub project_dir: ResolvedVc, @@ -719,7 +719,7 @@ impl NodeJsPool { pub(super) fn new( cwd: PathBuf, entrypoint: PathBuf, - env: HashMap, + env: FxHashMap, assets_for_source_mapping: ResolvedVc, assets_root: ResolvedVc, project_dir: ResolvedVc, diff --git a/turbopack/crates/turbopack-test-utils/Cargo.toml b/turbopack/crates/turbopack-test-utils/Cargo.toml index ed15eb0a6f6fd..7b5acc1d73c2b 100644 --- a/turbopack/crates/turbopack-test-utils/Cargo.toml +++ b/turbopack/crates/turbopack-test-utils/Cargo.toml @@ -24,6 +24,7 @@ turbo-tasks-fs = { workspace = true } turbo-tasks-hash = { workspace = true } turbopack-cli-utils = { workspace = true } turbopack-core = { workspace = true } +rustc-hash = { workspace = true } [build-dependencies] turbo-tasks-build = { workspace = true } diff --git a/turbopack/crates/turbopack-test-utils/src/snapshot.rs b/turbopack/crates/turbopack-test-utils/src/snapshot.rs index d4a2ab4836b23..f3c8160e0ccc3 100644 --- a/turbopack/crates/turbopack-test-utils/src/snapshot.rs +++ b/turbopack/crates/turbopack-test-utils/src/snapshot.rs @@ -1,12 +1,9 @@ -use std::{ - collections::{HashMap, HashSet}, - env, fs, - path::PathBuf, -}; +use std::{env, fs, path::PathBuf}; use anyhow::{anyhow, bail, Context, Result}; use once_cell::sync::Lazy; use regex::Regex; +use rustc_hash::{FxHashMap, FxHashSet}; use similar::TextDiff; use turbo_rcstr::RcStr; use turbo_tasks::{ReadRef, TryJoinIterExt, ValueToString, Vc}; @@ -33,7 +30,7 @@ pub async fn snapshot_issues>>( workspace_root: &str, ) -> Result<()> { let expected_issues = expected(issues_path).await?; - let mut seen = HashSet::new(); + let mut seen = FxHashSet::default(); for plain_issue in captured_issues.into_iter() { let title = styled_string_to_file_safe_string(&plain_issue.title) .replace('/', "__") @@ -85,8 +82,8 @@ pub async fn snapshot_issues>>( matches_expected(expected_issues, seen).await } -pub async fn expected(dir: Vc) -> Result>> { - let mut expected = HashSet::new(); +pub async fn expected(dir: Vc) -> Result>> { + let mut expected = FxHashSet::default(); let entries = dir.read_dir().await?; if let DirectoryContent::Entries(entries) = &*entries { for (file, entry) in entries { @@ -106,8 +103,8 @@ pub async fn expected(dir: Vc) -> Result>, - seen: HashSet>, + expected: FxHashSet>, + seen: FxHashSet>, ) -> Result<()> { for path in diff_paths(&expected, &seen).await? { let p = &path.await?.path; @@ -195,9 +192,9 @@ async fn remove_file(path: Vc) -> Result<()> { /// Vc hashes as a Vc, not as the file path, so we need to get /// the path to properly diff. async fn diff_paths( - left: &HashSet>, - right: &HashSet>, -) -> Result>> { + left: &FxHashSet>, + right: &FxHashSet>, +) -> Result>> { let mut map = left .iter() .map(|p| async move { Ok((p.await?.path.clone(), *p)) }) @@ -205,7 +202,7 @@ async fn diff_paths( .await? .iter() .cloned() - .collect::>(); + .collect::>(); for p in right { map.remove(&p.await?.path); } diff --git a/turbopack/crates/turbopack-tests/Cargo.toml b/turbopack/crates/turbopack-tests/Cargo.toml index 8586807bbaf96..850d1a3a2e18b 100644 --- a/turbopack/crates/turbopack-tests/Cargo.toml +++ b/turbopack/crates/turbopack-tests/Cargo.toml @@ -21,6 +21,7 @@ dunce = { workspace = true } futures = { workspace = true } indexmap = { workspace = true } once_cell = { workspace = true } +rustc-hash = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } testing = { workspace = true } diff --git a/turbopack/crates/turbopack-tests/tests/snapshot.rs b/turbopack/crates/turbopack-tests/tests/snapshot.rs index 4ac2c29f8f03f..47d656977fd33 100644 --- a/turbopack/crates/turbopack-tests/tests/snapshot.rs +++ b/turbopack/crates/turbopack-tests/tests/snapshot.rs @@ -3,14 +3,11 @@ mod util; -use std::{ - collections::{HashSet, VecDeque}, - fs, - path::PathBuf, -}; +use std::{collections::VecDeque, fs, path::PathBuf}; use anyhow::{bail, Context, Result}; use dunce::canonicalize; +use rustc_hash::FxHashSet; use serde::Deserialize; use serde_json::json; use turbo_rcstr::RcStr; @@ -451,7 +448,7 @@ async fn run_test_operation(resource: RcStr) -> Result> { bail!("Entry module is not chunkable, so it can't be used to bootstrap the application") }; - let mut seen = HashSet::new(); + let mut seen = FxHashSet::default(); let mut queue: VecDeque<_> = chunks.await?.iter().copied().collect(); let output_path = project_path.await?; @@ -478,7 +475,7 @@ async fn run_test_operation(resource: RcStr) -> Result> { async fn walk_asset( asset: ResolvedVc>, output_path: &ReadRef, - seen: &mut HashSet>, + seen: &mut FxHashSet>, queue: &mut VecDeque>>, ) -> Result<()> { let path = asset.ident().path().resolve().await?; diff --git a/turbopack/crates/turbopack-trace-server/src/bottom_up.rs b/turbopack/crates/turbopack-trace-server/src/bottom_up.rs index 39c025eb8d4de..26ebf157b88ee 100644 --- a/turbopack/crates/turbopack-trace-server/src/bottom_up.rs +++ b/turbopack/crates/turbopack-trace-server/src/bottom_up.rs @@ -1,4 +1,6 @@ -use std::{collections::HashMap, env, sync::Arc}; +use std::{env, sync::Arc}; + +use rustc_hash::FxHashMap; use crate::{ span::{SpanBottomUp, SpanIndex}, @@ -8,7 +10,7 @@ use crate::{ pub struct SpanBottomUpBuilder { // These values won't change after creation: pub self_spans: Vec, - pub children: HashMap, + pub children: FxHashMap, pub example_span: SpanIndex, } @@ -16,7 +18,7 @@ impl SpanBottomUpBuilder { pub fn new(example_span: SpanIndex) -> Self { Self { self_spans: vec![], - children: HashMap::new(), + children: FxHashMap::default(), example_span, } } @@ -40,7 +42,7 @@ pub fn build_bottom_up_graph<'a>( .ok() .and_then(|s| s.parse().ok()) .unwrap_or(usize::MAX); - let mut roots = HashMap::new(); + let mut roots = FxHashMap::default(); // unfortunately there is a rustc bug that fails the typechecking here // when using Either. This error appears diff --git a/turbopack/crates/turbopack-trace-server/src/main.rs b/turbopack/crates/turbopack-trace-server/src/main.rs index 82322e4a971df..f909176b8dd7e 100644 --- a/turbopack/crates/turbopack-trace-server/src/main.rs +++ b/turbopack/crates/turbopack-trace-server/src/main.rs @@ -4,7 +4,7 @@ use std::{hash::BuildHasherDefault, sync::Arc}; -use indexmap::IndexSet; +use indexmap::{IndexMap, IndexSet}; use rustc_hash::FxHasher; use self::{reader::TraceReader, server::serve, store_container::StoreContainer}; @@ -23,10 +23,11 @@ mod u64_empty_string; mod u64_string; mod viewer; -type FxIndexMap = indexmap::IndexMap>; +type FxIndexSet = IndexSet>; +type FxIndexMap = IndexMap>; fn main() { - let args: IndexSet = std::env::args().skip(1).collect(); + let args: FxIndexSet = std::env::args().skip(1).collect(); let mut iter = args.iter(); let arg = iter.next().expect("missing argument: trace file path"); diff --git a/turbopack/crates/turbopack-trace-server/src/reader/heaptrack.rs b/turbopack/crates/turbopack-trace-server/src/reader/heaptrack.rs index 9d732ebcff205..5eb5b33fc33f1 100644 --- a/turbopack/crates/turbopack-trace-server/src/reader/heaptrack.rs +++ b/turbopack/crates/turbopack-trace-server/src/reader/heaptrack.rs @@ -1,13 +1,9 @@ -use std::{ - collections::{HashMap, HashSet}, - env, - str::from_utf8, - sync::Arc, -}; +use std::{env, str::from_utf8, sync::Arc}; use anyhow::{bail, Context, Result}; use indexmap::map::Entry; use rustc_demangle::demangle; +use rustc_hash::{FxHashMap, FxHashSet}; use super::TraceFormat; use crate::{span::SpanIndex, store_container::StoreContainer, FxIndexMap}; @@ -94,13 +90,13 @@ pub struct HeaptrackFormat { last_timestamp: u64, strings: Vec, traces: Vec, - ip_parent_map: HashMap<(usize, SpanIndex), usize>, + ip_parent_map: FxHashMap<(usize, SpanIndex), usize>, trace_instruction_pointers: Vec, instruction_pointers: FxIndexMap, allocations: Vec, spans: usize, - collapse_crates: HashSet, - expand_crates: HashSet, + collapse_crates: FxHashSet, + expand_crates: FxHashSet, expand_recursion: bool, allocated_memory: u64, temp_allocated_memory: u64, @@ -120,7 +116,7 @@ impl HeaptrackFormat { ip_index: 0, parent_trace_index: 0, }], - ip_parent_map: HashMap::new(), + ip_parent_map: FxHashMap::default(), instruction_pointers: { let mut map = FxIndexMap::with_capacity_and_hasher(2, Default::default()); map.insert( @@ -185,7 +181,7 @@ impl TraceFormat for HeaptrackFormat { fn read(&mut self, mut buffer: &[u8], _reuse: &mut Self::Reused) -> anyhow::Result { let mut bytes_read = 0; - let mut outdated_spans = HashSet::new(); + let mut outdated_spans = FxHashSet::default(); let mut store = self.store.write(); 'outer: loop { let Some(line_end) = buffer.iter().position(|b| *b == b'\n') else { diff --git a/turbopack/crates/turbopack-trace-server/src/reader/nextjs.rs b/turbopack/crates/turbopack-trace-server/src/reader/nextjs.rs index 6b0d7535fe358..bc913088cb236 100644 --- a/turbopack/crates/turbopack-trace-server/src/reader/nextjs.rs +++ b/turbopack/crates/turbopack-trace-server/src/reader/nextjs.rs @@ -1,10 +1,6 @@ -use std::{ - borrow::Cow, - collections::{HashMap, HashSet}, - fmt::Display, - sync::Arc, -}; +use std::{borrow::Cow, fmt::Display, sync::Arc}; +use rustc_hash::{FxHashMap, FxHashSet}; use serde::Deserialize; use super::TraceFormat; @@ -12,16 +8,16 @@ use crate::{span::SpanIndex, store_container::StoreContainer, FxIndexMap}; pub struct NextJsFormat { store: Arc, - id_mapping: HashMap, - queued_children: HashMap>, + id_mapping: FxHashMap, + queued_children: FxHashMap>, } impl NextJsFormat { pub fn new(store: Arc) -> Self { Self { store, - id_mapping: HashMap::new(), - queued_children: HashMap::new(), + id_mapping: FxHashMap::default(), + queued_children: FxHashMap::default(), } } } @@ -31,7 +27,7 @@ impl TraceFormat for NextJsFormat { fn read(&mut self, mut buffer: &[u8], _reuse: &mut Self::Reused) -> anyhow::Result { let mut bytes_read = 0; - let mut outdated_spans = HashSet::new(); + let mut outdated_spans = FxHashSet::default(); loop { let Some(line_end) = buffer.iter().position(|b| *b == b'\n') else { break; diff --git a/turbopack/crates/turbopack-trace-server/src/reader/turbopack.rs b/turbopack/crates/turbopack-trace-server/src/reader/turbopack.rs index c944690f407b3..d34f87820d4b9 100644 --- a/turbopack/crates/turbopack-trace-server/src/reader/turbopack.rs +++ b/turbopack/crates/turbopack-trace-server/src/reader/turbopack.rs @@ -1,12 +1,13 @@ use std::{ borrow::Cow, - collections::{hash_map::Entry, HashMap, HashSet}, + collections::hash_map::Entry, mem::transmute, ops::{Deref, DerefMut}, sync::Arc, }; use anyhow::Result; +use rustc_hash::{FxHashMap, FxHashSet}; use turbopack_trace_utils::tracing::{TraceRow, TraceValue}; use super::TraceFormat; @@ -129,24 +130,24 @@ struct QueuedRows { pub struct TurbopackFormat { store: Arc, - id_mapping: HashMap, - queued_rows: HashMap, - outdated_spans: HashSet, - thread_stacks: HashMap>, - thread_allocation_counters: HashMap, - self_time_started: HashMap<(u64, u64), u64>, + id_mapping: FxHashMap, + queued_rows: FxHashMap, + outdated_spans: FxHashSet, + thread_stacks: FxHashMap>, + thread_allocation_counters: FxHashMap, + self_time_started: FxHashMap<(u64, u64), u64>, } impl TurbopackFormat { pub fn new(store: Arc) -> Self { Self { store, - id_mapping: HashMap::new(), - queued_rows: HashMap::new(), - outdated_spans: HashSet::new(), - thread_stacks: HashMap::new(), - thread_allocation_counters: HashMap::new(), - self_time_started: HashMap::new(), + id_mapping: FxHashMap::default(), + queued_rows: FxHashMap::default(), + outdated_spans: FxHashSet::default(), + thread_stacks: FxHashMap::default(), + thread_allocation_counters: FxHashMap::default(), + self_time_started: FxHashMap::default(), } } diff --git a/turbopack/crates/turbopack-trace-server/src/span.rs b/turbopack/crates/turbopack-trace-server/src/span.rs index 93f5be1a73a4f..38ce5b977afd3 100644 --- a/turbopack/crates/turbopack-trace-server/src/span.rs +++ b/turbopack/crates/turbopack-trace-server/src/span.rs @@ -1,9 +1,10 @@ use std::{ - collections::HashMap, num::NonZeroUsize, sync::{Arc, OnceLock}, }; +use rustc_hash::FxHashMap; + pub type SpanIndex = NonZeroUsize; pub struct Span { @@ -61,7 +62,7 @@ pub struct SpanTimeData { pub struct SpanExtra { pub graph: OnceLock>, pub bottom_up: OnceLock>>, - pub search_index: OnceLock>>, + pub search_index: OnceLock>>, } #[derive(Default)] diff --git a/turbopack/crates/turbopack-trace-server/src/span_ref.rs b/turbopack/crates/turbopack-trace-server/src/span_ref.rs index ae2a61cb3e55b..c8299e516c5a1 100644 --- a/turbopack/crates/turbopack-trace-server/src/span_ref.rs +++ b/turbopack/crates/turbopack-trace-server/src/span_ref.rs @@ -1,11 +1,12 @@ use std::{ cmp::max, - collections::{HashMap, HashSet, VecDeque}, + collections::VecDeque, fmt::{Debug, Formatter}, vec, }; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; +use rustc_hash::{FxHashMap, FxHashSet}; use crate::{ bottom_up::build_bottom_up_graph, @@ -388,7 +389,7 @@ impl<'a> SpanRef<'a> { pub fn search(&self, query: &str) -> impl Iterator> { let mut query_items = query.split(",").map(str::trim); let index = self.search_index(); - let mut result = HashSet::new(); + let mut result = FxHashSet::default(); let query = query_items.next().unwrap(); for (key, spans) in index { if key.contains(query) { @@ -396,7 +397,7 @@ impl<'a> SpanRef<'a> { } } for query in query_items { - let mut and_result = HashSet::new(); + let mut and_result = FxHashSet::default(); for (key, spans) in index { if key.contains(query) { and_result.extend(spans.iter().copied()); @@ -412,9 +413,9 @@ impl<'a> SpanRef<'a> { }) } - fn search_index(&self) -> &HashMap> { + fn search_index(&self) -> &FxHashMap> { self.extra().search_index.get_or_init(|| { - let mut index: HashMap> = HashMap::new(); + let mut index: FxHashMap> = FxHashMap::default(); let mut queue = VecDeque::with_capacity(8); queue.push_back(*self); while let Some(span) = queue.pop_front() { diff --git a/turbopack/crates/turbopack-trace-server/src/store.rs b/turbopack/crates/turbopack-trace-server/src/store.rs index 045144d8e705c..9a77c6f6b67bb 100644 --- a/turbopack/crates/turbopack-trace-server/src/store.rs +++ b/turbopack/crates/turbopack-trace-server/src/store.rs @@ -1,12 +1,13 @@ use std::{ cmp::{max, min}, - collections::HashSet, env, mem::replace, num::NonZeroUsize, sync::{atomic::AtomicU64, OnceLock}, }; +use rustc_hash::FxHashSet; + use crate::{ self_time_tree::SelfTimeTree, span::{Span, SpanEvent, SpanIndex}, @@ -83,7 +84,7 @@ impl Store { category: String, name: String, args: Vec<(String, String)>, - outdated_spans: &mut HashSet, + outdated_spans: &mut FxHashSet, ) -> SpanIndex { let id = SpanIndex::new(self.spans.len()).unwrap(); self.spans.push(Span { @@ -129,7 +130,7 @@ impl Store { &mut self, span_index: SpanIndex, args: Vec<(String, String)>, - outdated_spans: &mut HashSet, + outdated_spans: &mut FxHashSet, ) { let span = &mut self.spans[span_index.get()]; span.args.extend(args); @@ -158,7 +159,7 @@ impl Store { start: u64, end: u64, span_index: SpanIndex, - outdated_spans: &mut HashSet, + outdated_spans: &mut FxHashSet, ) { if let Some(tree) = self.self_time_tree.as_mut() { if *self.max_self_time_lookup_time.get_mut() >= start { @@ -175,7 +176,7 @@ impl Store { span_index: SpanIndex, start: u64, end: u64, - outdated_spans: &mut HashSet, + outdated_spans: &mut FxHashSet, ) { let span = &mut self.spans[span_index.get()]; let time_data = span.time_data_mut(); @@ -194,7 +195,7 @@ impl Store { span_index: SpanIndex, start_time: u64, total_time: u64, - outdated_spans: &mut HashSet, + outdated_spans: &mut FxHashSet, ) { let span = SpanRef { span: &self.spans[span_index.get()], @@ -258,7 +259,7 @@ impl Store { &mut self, span_index: SpanIndex, parent: SpanIndex, - outdated_spans: &mut HashSet, + outdated_spans: &mut FxHashSet, ) { outdated_spans.insert(span_index); let span = &mut self.spans[span_index.get()]; @@ -288,7 +289,7 @@ impl Store { span_index: SpanIndex, allocation: u64, count: u64, - outdated_spans: &mut HashSet, + outdated_spans: &mut FxHashSet, ) { let span = &mut self.spans[span_index.get()]; outdated_spans.insert(span_index); @@ -301,7 +302,7 @@ impl Store { span_index: SpanIndex, deallocation: u64, count: u64, - outdated_spans: &mut HashSet, + outdated_spans: &mut FxHashSet, ) { let span = &mut self.spans[span_index.get()]; outdated_spans.insert(span_index); @@ -314,7 +315,7 @@ impl Store { span.is_complete = true; } - pub fn invalidate_outdated_spans(&mut self, outdated_spans: &HashSet) { + pub fn invalidate_outdated_spans(&mut self, outdated_spans: &FxHashSet) { fn invalidate_span(span: &mut Span) { if let Some(time_data) = span.time_data.get_mut() { time_data.end.take(); diff --git a/turbopack/crates/turbopack-trace-server/src/viewer.rs b/turbopack/crates/turbopack-trace-server/src/viewer.rs index c27e33ed1b37f..dff6e97446540 100644 --- a/turbopack/crates/turbopack-trace-server/src/viewer.rs +++ b/turbopack/crates/turbopack-trace-server/src/viewer.rs @@ -1,11 +1,9 @@ -use std::{ - cmp::{max, Reverse}, - collections::{HashMap, HashSet}, -}; +use std::cmp::{max, Reverse}; use either::Either; use itertools::Itertools; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; +use rustc_hash::{FxHashMap, FxHashSet}; use serde::{Deserialize, Serialize}; use crate::{ @@ -22,7 +20,7 @@ const EXTRA_HEIGHT: u64 = 5; #[derive(Default)] pub struct Viewer { - span_options: HashMap, + span_options: FxHashMap, } #[derive(Clone, Copy, Debug)] @@ -341,8 +339,8 @@ impl Viewer { } pub fn compute_update(&mut self, store: &Store, view_rect: &ViewRect) -> Update { - let mut highlighted_spans: HashSet = HashSet::new(); - let mut highlighted_span_parents: HashSet = HashSet::new(); + let mut highlighted_spans: FxHashSet = FxHashSet::default(); + let mut highlighted_span_parents: FxHashSet = FxHashSet::default(); let search_mode = !view_rect.query.is_empty(); let (query, focus_mode) = if let Some(query) = view_rect.query.strip_suffix('!') { (query, true) diff --git a/turbopack/crates/turbopack-trace-utils/src/filter_layer.rs b/turbopack/crates/turbopack-trace-utils/src/filter_layer.rs index d283538ff10e2..c9bbbd0c8c8cd 100644 --- a/turbopack/crates/turbopack-trace-utils/src/filter_layer.rs +++ b/turbopack/crates/turbopack-trace-utils/src/filter_layer.rs @@ -1,18 +1,18 @@ -use std::{collections::HashMap, hash::BuildHasherDefault, str::FromStr}; +use std::str::FromStr; use anyhow::Result; -use rustc_hash::FxHasher; +use rustc_hash::FxHashMap; use tracing::{level_filters::LevelFilter, Subscriber}; use tracing_subscriber::Layer; pub struct FilterLayer { - config: HashMap>, + config: FxHashMap, global_level: LevelFilter, } impl FilterLayer { pub fn try_new(input: &str) -> Result { - let mut config = HashMap::default(); + let mut config = FxHashMap::default(); let mut global_level = LevelFilter::OFF; for entry in input.split(',') { if entry.is_empty() { diff --git a/turbopack/crates/turbopack/src/graph/mod.rs b/turbopack/crates/turbopack/src/graph/mod.rs index 49b554cc9beb5..2083e4e7a9f92 100644 --- a/turbopack/crates/turbopack/src/graph/mod.rs +++ b/turbopack/crates/turbopack/src/graph/mod.rs @@ -1,6 +1,5 @@ -use std::collections::HashSet; - use anyhow::Result; +use rustc_hash::FxHashSet; use turbo_tasks::{ResolvedVc, Vc}; use turbopack_core::output::OutputAsset; @@ -9,8 +8,8 @@ pub enum AggregatedGraph { Leaf(ResolvedVc>), Node { depth: usize, - content: HashSet>, - references: HashSet>, + content: FxHashSet>, + references: FxHashSet>, }, } @@ -47,7 +46,7 @@ impl AggregatedGraph { async fn references(self: Vc) -> Result> { Ok(match &*self.await? { AggregatedGraph::Leaf(asset) => { - let mut refs = HashSet::new(); + let mut refs = FxHashSet::default(); for reference in asset.references().await? { if asset != reference { refs.insert(AggregatedGraph::leaf(**reference).to_resolved().await?); @@ -56,7 +55,7 @@ impl AggregatedGraph { AggregatedGraphsSet { set: refs }.into() } AggregatedGraph::Node { references, .. } => { - let mut set = HashSet::new(); + let mut set = FxHashSet::default(); for item in references .iter() .map(|&reference| aggregate_more(*reference)) @@ -83,9 +82,9 @@ impl AggregatedGraph { #[turbo_tasks::function] async fn valued_references(self: Vc) -> Result> { let self_cost = self.cost().await?.0; - let mut inner = HashSet::new(); - let mut outer = HashSet::new(); - let mut references = HashSet::new(); + let mut inner = FxHashSet::default(); + let mut outer = FxHashSet::default(); + let mut references = FxHashSet::default(); for (reference, cost) in self .references() .await? @@ -131,9 +130,9 @@ struct AggregationCost(usize); async fn aggregate_more(node: ResolvedVc) -> Result> { let node_data = node.await?; let depth = node_data.depth(); - let mut in_progress = HashSet::new(); - let mut content = HashSet::new(); - let mut references = HashSet::new(); + let mut in_progress = FxHashSet::default(); + let mut content = FxHashSet::default(); + let mut references = FxHashSet::default(); in_progress.insert(node); // only one kind of aggregation can't eliminate cycles with that @@ -181,18 +180,18 @@ async fn aggregate_more(node: ResolvedVc) -> Result>, + pub set: FxHashSet>, } #[turbo_tasks::value(shared)] pub enum AggregatedGraphNodeContent { Asset(ResolvedVc>), - Children(HashSet>), + Children(FxHashSet>), } #[turbo_tasks::value(shared)] struct AggregatedGraphsValuedReferences { - pub inner: HashSet>, - pub outer: HashSet>, - pub references: HashSet>, + pub inner: FxHashSet>, + pub outer: FxHashSet>, + pub references: FxHashSet>, } diff --git a/turbopack/crates/turbopack/src/transition/mod.rs b/turbopack/crates/turbopack/src/transition/mod.rs index c381850997e80..0dbae9f108464 100644 --- a/turbopack/crates/turbopack/src/transition/mod.rs +++ b/turbopack/crates/turbopack/src/transition/mod.rs @@ -1,11 +1,10 @@ pub(crate) mod context_transition; pub(crate) mod full_context_transition; -use std::collections::HashMap; - use anyhow::Result; pub use context_transition::ContextTransition; pub use full_context_transition::FullContextTransition; +use rustc_hash::FxHashMap; use turbo_rcstr::RcStr; use turbo_tasks::{ResolvedVc, Value, ValueDefault, Vc}; use turbopack_core::{ @@ -121,7 +120,7 @@ pub trait Transition { #[turbo_tasks::value(shared)] #[derive(Default)] pub struct TransitionOptions { - pub named_transitions: HashMap>>, + pub named_transitions: FxHashMap>>, pub transition_rules: Vec, pub placeholder_for_future_extensions: (), } diff --git a/turbopack/xtask/Cargo.toml b/turbopack/xtask/Cargo.toml index b8f6de3f9201a..5fad7ba63190c 100644 --- a/turbopack/xtask/Cargo.toml +++ b/turbopack/xtask/Cargo.toml @@ -25,6 +25,7 @@ indexmap = { workspace = true } inquire = { version = "0.5.1" } num-format = "0.4.4" owo-colors = { workspace = true } +rustc-hash = { workspace = true } semver = { workspace = true } serde = { workspace = true } serde_json = { workspace = true, features = ["preserve_order"] } diff --git a/turbopack/xtask/src/main.rs b/turbopack/xtask/src/main.rs index f51ada5d81f8f..0b3b73f682989 100644 --- a/turbopack/xtask/src/main.rs +++ b/turbopack/xtask/src/main.rs @@ -1,5 +1,4 @@ use std::{ - collections::{HashMap, HashSet}, env::{current_dir, var_os}, path::PathBuf, process, @@ -18,6 +17,7 @@ mod visualize_bundler_bench; use nft_bench::show_result; use patch_package_json::PatchPackageJsonArgs; use publish::{publish_workspace, run_bump, run_publish}; +use rustc_hash::{FxHashMap, FxHashSet}; fn cli() -> Command { Command::new("xtask") @@ -94,7 +94,7 @@ fn main() -> Result<()> { if is_bump { let names = sub_matches .get_many::("NAME") - .map(|names| names.cloned().collect::>()) + .map(|names| names.cloned().collect::>()) .unwrap_or_default(); run_bump(names, dry_run); } @@ -125,14 +125,14 @@ fn main() -> Result<()> { let only_swc_set = swc_packages .iter() .map(|p| p.name.as_str()) - .collect::>(); + .collect::>(); let packages = lock .packages .iter() .map(|p| (format!("{}@{}", p.name, p.version), p)) - .collect::>(); + .collect::>(); let mut queue = swc_packages.clone(); - let mut set = HashSet::new(); + let mut set = FxHashSet::default(); while let Some(package) = queue.pop() { for dep in package.dependencies.iter() { let ident = format!("{}@{}", dep.name, dep.version); @@ -176,7 +176,7 @@ fn main() -> Result<()> { let path = sub_matches .get_one::("PATH_TO_SUMMARY_JSON") .expect("PATH_TO_SUMMARY_JSON is required"); - let bundlers: Option> = sub_matches + let bundlers: Option> = sub_matches .get_one::("bundlers") .map(|s| s.split(',').collect()); diff --git a/turbopack/xtask/src/publish.rs b/turbopack/xtask/src/publish.rs index db0543e96adec..552606ee0a996 100644 --- a/turbopack/xtask/src/publish.rs +++ b/turbopack/xtask/src/publish.rs @@ -1,12 +1,7 @@ -use std::{ - collections::{HashMap, HashSet}, - env, fs, - path::PathBuf, - process, - str::FromStr, -}; +use std::{env, fs, path::PathBuf, process, str::FromStr}; use owo_colors::OwoColorize; +use rustc_hash::{FxHashMap, FxHashSet}; use semver::{Prerelease, Version}; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -170,7 +165,7 @@ pub fn run_publish(name: &str) { let optional_dependencies_with_version = optional_dependencies .into_iter() .map(|name| (name, version.clone())) - .collect::>(); + .collect::>(); let pkg_json_content = fs::read(package_dir.join("../../package.json")).expect("Unable to read package.json"); let mut pkg_json: Value = serde_json::from_slice(&pkg_json_content).unwrap(); @@ -221,7 +216,7 @@ struct PackageJson { path: String, } -pub fn run_bump(names: HashSet, dry_run: bool) { +pub fn run_bump(names: FxHashSet, dry_run: bool) { let workspaces_list_text = Command::program("pnpm") .args(["ls", "-r", "--depth", "-1", "--json"]) .error_message("List workspaces failed") diff --git a/turbopack/xtask/src/summarize_bench/mod.rs b/turbopack/xtask/src/summarize_bench/mod.rs index 59a643e88af91..d96c267656a67 100644 --- a/turbopack/xtask/src/summarize_bench/mod.rs +++ b/turbopack/xtask/src/summarize_bench/mod.rs @@ -1,8 +1,9 @@ pub(crate) mod data; use std::{ - collections::{hash_map::Entry, BTreeMap, HashMap}, + collections::{hash_map::Entry, BTreeMap}, fs::File, + hash::BuildHasherDefault, path::{Path, PathBuf}, time::{Duration, UNIX_EPOCH}, }; @@ -10,11 +11,14 @@ use std::{ use anyhow::{anyhow, Context}; use chrono::{DateTime, Utc}; use indexmap::IndexSet; +use rustc_hash::{FxHashMap, FxHasher}; use walkdir::WalkDir; use self::data::Benchmark; use crate::summarize_bench::data::{BaseBenchmarks, CStats}; +type FxIndexSet = IndexSet>; + #[derive(Debug)] struct BenchDataFile { path: PathBuf, @@ -52,7 +56,7 @@ impl<'a> TryFrom<&'a Path> for BenchDataFile { } pub fn process_all(path: PathBuf) { - let mut map = HashMap::new(); + let mut map = FxHashMap::default(); for entry in WalkDir::new(&path) .into_iter() .filter_map(Result::ok) @@ -63,14 +67,14 @@ pub fn process_all(path: PathBuf) { { let data_file_result: Result = entry.path().try_into(); if let Ok(data_file) = data_file_result { - let inner_map: &mut HashMap<_, _> = map.entry(data_file.system.clone()).or_default(); + let inner_map: &mut FxHashMap<_, _> = map.entry(data_file.system.clone()).or_default(); let items: &mut Vec = inner_map.entry(data_file.sha.clone()).or_default(); items.push(data_file); } } for (system, inner_map) in map { - let mut latest: HashMap = HashMap::new(); + let mut latest: FxHashMap = FxHashMap::default(); for (sha, data_files) in inner_map { let min_ts = data_files.iter().map(|d| d.timestamp).min().unwrap(); let max_ts = data_files.iter().map(|d| d.timestamp).max().unwrap(); @@ -85,7 +89,7 @@ pub fn process_all(path: PathBuf) { data }) .collect::>(); - let mut by_name = HashMap::new(); + let mut by_name = FxHashMap::default(); for (i, data) in items.iter().enumerate() { for (name, bench) in data.benchmarks.iter() { let list: &mut Vec<_> = by_name.entry(name).or_default(); @@ -143,7 +147,7 @@ pub fn process_all(path: PathBuf) { let all_benchmark_keys = items .iter() .flat_map(|b| b.benchmarks.keys()) - .collect::>(); + .collect::>(); for key in all_benchmark_keys { let (ts, bench) = items .iter() diff --git a/turbopack/xtask/src/visualize_bundler_bench.rs b/turbopack/xtask/src/visualize_bundler_bench.rs index 292f99528c16b..1261924820af6 100644 --- a/turbopack/xtask/src/visualize_bundler_bench.rs +++ b/turbopack/xtask/src/visualize_bundler_bench.rs @@ -1,5 +1,5 @@ use std::{ - collections::{BTreeMap, HashSet}, + collections::BTreeMap, fs::{self, File}, io::BufReader, path::PathBuf, @@ -15,6 +15,7 @@ use plotters::{ series::LineSeries, style::{Color, RGBAColor, RGBColor}, }; +use rustc_hash::FxHashSet; use crate::summarize_bench::data::{BaseBenchmarks, CStats}; @@ -117,7 +118,7 @@ impl Bundler { } } -pub fn generate(summary_path: PathBuf, filter_bundlers: Option>) -> Result<()> { +pub fn generate(summary_path: PathBuf, filter_bundlers: Option>) -> Result<()> { let summary_file = File::open(&summary_path)?; let reader = BufReader::new(summary_file); let summary: BaseBenchmarks = serde_json::from_reader(reader)?; @@ -260,7 +261,7 @@ fn generate_scaling(output_path: PathBuf, by_bench: &ByBench) -> Result<()> { for theme in THEMES { for (bench_name, by_bundler) in by_bench { - let module_counts: HashSet<_> = by_bundler + let module_counts: FxHashSet<_> = by_bundler .values() .flat_map(|by_module_count| by_module_count.keys()) .copied()