From 88dfe4d2766587b811863cfc2bd1668e6fbadb6a Mon Sep 17 00:00:00 2001 From: Laurenz Date: Thu, 31 Jul 2025 10:45:03 +0200 Subject: [PATCH 01/19] Use `rustc-hash` for hash maps and sets (#6678) --- Cargo.lock | 13 +++++++ Cargo.toml | 1 + crates/typst-cli/Cargo.toml | 1 + crates/typst-cli/src/watch.rs | 10 +++--- crates/typst-cli/src/world.rs | 6 ++-- crates/typst-eval/Cargo.toml | 1 + crates/typst-eval/src/binding.rs | 5 ++- crates/typst-eval/src/code.rs | 2 +- crates/typst-html/Cargo.toml | 1 + crates/typst-html/src/document.rs | 8 ++--- crates/typst-html/src/link.rs | 19 ++++++----- crates/typst-ide/Cargo.toml | 1 + crates/typst-ide/src/analyze.rs | 5 ++- crates/typst-ide/src/complete.rs | 9 ++--- crates/typst-ide/src/tests.rs | 6 ++-- crates/typst-layout/Cargo.toml | 1 + crates/typst-layout/src/flow/mod.rs | 6 ++-- crates/typst-layout/src/pages/collect.rs | 5 ++- crates/typst-library/Cargo.toml | 1 + crates/typst-library/src/engine.rs | 4 +-- crates/typst-library/src/foundations/dict.rs | 11 +++--- crates/typst-library/src/foundations/scope.rs | 3 +- .../typst-library/src/foundations/styles.rs | 6 ++-- .../typst-library/src/foundations/symbol.rs | 5 +-- .../src/introspection/introspector.rs | 21 ++++++------ .../src/introspection/locator.rs | 6 ++-- .../typst-library/src/model/bibliography.rs | 20 ++++++----- crates/typst-library/src/text/lang.rs | 12 +++---- .../typst-library/src/visualize/image/svg.rs | 10 +++--- crates/typst-pdf/Cargo.toml | 1 + crates/typst-pdf/src/convert.rs | 33 +++++++++--------- crates/typst-svg/Cargo.toml | 1 + crates/typst-svg/src/lib.rs | 10 ++++-- crates/typst-syntax/Cargo.toml | 1 + crates/typst-syntax/src/file.rs | 7 ++-- crates/typst-syntax/src/parser.rs | 34 +++++++++---------- crates/typst-utils/Cargo.toml | 1 + crates/typst-utils/src/pico.rs | 10 +++--- crates/typst/Cargo.toml | 1 + crates/typst/src/lib.rs | 4 +-- docs/Cargo.toml | 1 + docs/src/contribs.rs | 4 +-- docs/src/lib.rs | 5 ++- tests/Cargo.toml | 1 + tests/src/collect.rs | 8 ++--- tests/src/world.rs | 6 ++-- 46 files changed, 183 insertions(+), 144 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bcf430a43..d35e708bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2906,6 +2906,7 @@ version = "0.13.1" dependencies = [ "comemo", "ecow", + "rustc-hash", "typst-eval", "typst-html", "typst-layout", @@ -2941,6 +2942,7 @@ dependencies = [ "parking_lot", "pathdiff", "rayon", + "rustc-hash", "same-file", "self-replace", "semver", @@ -2981,6 +2983,7 @@ dependencies = [ "ecow", "heck", "pulldown-cmark", + "rustc-hash", "serde", "serde_json", "serde_yaml 0.9.34+deprecated", @@ -3003,6 +3006,7 @@ dependencies = [ "comemo", "ecow", "indexmap 2.7.1", + "rustc-hash", "stacker", "toml", "typst-library", @@ -3033,6 +3037,7 @@ dependencies = [ "comemo", "ecow", "palette", + "rustc-hash", "time", "typst-assets", "typst-library", @@ -3051,6 +3056,7 @@ dependencies = [ "ecow", "once_cell", "pathdiff", + "rustc-hash", "serde", "typst", "typst-assets", @@ -3100,6 +3106,7 @@ dependencies = [ "icu_segmenter", "kurbo", "memchr", + "rustc-hash", "rustybuzz", "smallvec", "ttf-parser", @@ -3151,6 +3158,7 @@ dependencies = [ "regex-syntax", "roxmltree", "rust_decimal", + "rustc-hash", "rustybuzz", "serde", "serde_json", @@ -3200,6 +3208,7 @@ dependencies = [ "infer", "krilla", "krilla-svg", + "rustc-hash", "serde", "typst-assets", "typst-library", @@ -3253,6 +3262,7 @@ dependencies = [ "flate2", "hayro", "image", + "rustc-hash", "ttf-parser", "typst-assets", "typst-library", @@ -3268,6 +3278,7 @@ name = "typst-syntax" version = "0.13.1" dependencies = [ "ecow", + "rustc-hash", "serde", "toml", "typst-timing", @@ -3290,6 +3301,7 @@ dependencies = [ "parking_lot", "rayon", "regex", + "rustc-hash", "tiny-skia", "typst", "typst-assets", @@ -3321,6 +3333,7 @@ dependencies = [ "once_cell", "portable-atomic", "rayon", + "rustc-hash", "siphasher", "thin-vec", "unicode-math-class", diff --git a/Cargo.toml b/Cargo.toml index 259a8a9f3..04c25cb6b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ fastrand = "2.3" flate2 = "1" fontdb = { version = "0.23", default-features = false } fs_extra = "1.3" +rustc-hash = "2.1" glidesort = "0.1.2" hayagriva = "0.8.1" hayro-syntax = { git = "https://github.com/LaurenzV/hayro", rev = "e701f95" } diff --git a/crates/typst-cli/Cargo.toml b/crates/typst-cli/Cargo.toml index 792cabae1..dcc4af868 100644 --- a/crates/typst-cli/Cargo.toml +++ b/crates/typst-cli/Cargo.toml @@ -41,6 +41,7 @@ open = { workspace = true } parking_lot = { workspace = true } pathdiff = { workspace = true } rayon = { workspace = true } +rustc-hash = { workspace = true } same-file = { workspace = true } self-replace = { workspace = true, optional = true } semver = { workspace = true } diff --git a/crates/typst-cli/src/watch.rs b/crates/typst-cli/src/watch.rs index 151c0ca1d..860ae8ebd 100644 --- a/crates/typst-cli/src/watch.rs +++ b/crates/typst-cli/src/watch.rs @@ -1,4 +1,3 @@ -use std::collections::{HashMap, HashSet}; use std::io::{self, Write}; use std::iter; use std::path::PathBuf; @@ -9,6 +8,7 @@ use codespan_reporting::term::termcolor::WriteColor; use codespan_reporting::term::{self, termcolor}; use ecow::eco_format; use notify::{Event, RecommendedWatcher, RecursiveMode, Watcher as _}; +use rustc_hash::{FxHashMap, FxHashSet}; use same_file::is_same_file; use typst::diag::{StrResult, bail, warning}; use typst::syntax::Span; @@ -91,10 +91,10 @@ struct Watcher { /// Keeps track of which paths are watched via `watcher`. The boolean is /// used during updating for mark-and-sweep garbage collection of paths we /// should unwatch. - watched: HashMap, + watched: FxHashMap, /// A set of files that should be watched, but don't exist. We manually poll /// for those. - missing: HashSet, + missing: FxHashSet, } impl Watcher { @@ -127,8 +127,8 @@ impl Watcher { output, rx, watcher, - watched: HashMap::new(), - missing: HashSet::new(), + watched: FxHashMap::default(), + missing: FxHashSet::default(), }) } diff --git a/crates/typst-cli/src/world.rs b/crates/typst-cli/src/world.rs index 34ebda64b..6dd362524 100644 --- a/crates/typst-cli/src/world.rs +++ b/crates/typst-cli/src/world.rs @@ -1,4 +1,3 @@ -use std::collections::HashMap; use std::io::Read; use std::path::{Path, PathBuf}; use std::sync::{LazyLock, OnceLock}; @@ -7,6 +6,7 @@ use std::{fmt, fs, io, mem}; use chrono::{DateTime, Datelike, FixedOffset, Local, Utc}; use ecow::{EcoString, eco_format}; use parking_lot::Mutex; +use rustc_hash::FxHashMap; use typst::diag::{FileError, FileResult}; use typst::foundations::{Bytes, Datetime, Dict, IntoValue}; use typst::syntax::{FileId, Lines, Source, VirtualPath}; @@ -41,7 +41,7 @@ pub struct SystemWorld { /// Locations of and storage for lazily loaded fonts. fonts: Vec, /// Maps file ids to source files and buffers. - slots: Mutex>, + slots: Mutex>, /// Holds information about where packages are stored. package_storage: PackageStorage, /// The current datetime if requested. This is stored here to ensure it is @@ -139,7 +139,7 @@ impl SystemWorld { library: LazyHash::new(library), book: LazyHash::new(fonts.book), fonts: fonts.fonts, - slots: Mutex::new(HashMap::new()), + slots: Mutex::new(FxHashMap::default()), package_storage: package::storage(&world_args.package), now, }) diff --git a/crates/typst-eval/Cargo.toml b/crates/typst-eval/Cargo.toml index b39382ffe..d4fb0235b 100644 --- a/crates/typst-eval/Cargo.toml +++ b/crates/typst-eval/Cargo.toml @@ -21,6 +21,7 @@ typst-utils = { workspace = true } comemo = { workspace = true } ecow = { workspace = true } indexmap = { workspace = true } +rustc-hash = { workspace = true } toml = { workspace = true } unicode-segmentation = { workspace = true } diff --git a/crates/typst-eval/src/binding.rs b/crates/typst-eval/src/binding.rs index 9a53ac069..ccfb38583 100644 --- a/crates/typst-eval/src/binding.rs +++ b/crates/typst-eval/src/binding.rs @@ -1,6 +1,5 @@ -use std::collections::HashSet; - use ecow::eco_format; +use rustc_hash::FxHashSet; use typst_library::diag::{At, SourceDiagnostic, SourceResult, bail, error}; use typst_library::foundations::{Array, Dict, Value}; use typst_syntax::ast::{self, AstNode}; @@ -137,7 +136,7 @@ where F: Fn(&mut Vm, ast::Expr, Value) -> SourceResult<()>, { let mut sink = None; - let mut used = HashSet::new(); + let mut used = FxHashSet::default(); for p in destruct.items() { match p { diff --git a/crates/typst-eval/src/code.rs b/crates/typst-eval/src/code.rs index d3e0c937f..d15089f9a 100644 --- a/crates/typst-eval/src/code.rs +++ b/crates/typst-eval/src/code.rs @@ -246,7 +246,7 @@ impl Eval for ast::Dict<'_> { type Output = Dict; fn eval(self, vm: &mut Vm) -> SourceResult { - let mut map = indexmap::IndexMap::new(); + let mut map = indexmap::IndexMap::default(); let mut invalid_keys = eco_vec![]; for item in self.items() { diff --git a/crates/typst-html/Cargo.toml b/crates/typst-html/Cargo.toml index 54cad0124..8d592bc5a 100644 --- a/crates/typst-html/Cargo.toml +++ b/crates/typst-html/Cargo.toml @@ -24,6 +24,7 @@ bumpalo = { workspace = true } comemo = { workspace = true } ecow = { workspace = true } palette = { workspace = true } +rustc-hash = { workspace = true } time = { workspace = true } [lints] diff --git a/crates/typst-html/src/document.rs b/crates/typst-html/src/document.rs index ca84d3354..5345e5911 100644 --- a/crates/typst-html/src/document.rs +++ b/crates/typst-html/src/document.rs @@ -1,7 +1,7 @@ -use std::collections::HashSet; use std::num::NonZeroUsize; use comemo::{Tracked, TrackedMut}; +use rustc_hash::FxHashSet; use typst_library::World; use typst_library::diag::{SourceResult, bail}; use typst_library::engine::{Engine, Route, Sink, Traced}; @@ -87,7 +87,7 @@ fn html_document_impl( children.iter().copied(), )?; - let mut link_targets = HashSet::new(); + let mut link_targets = FxHashSet::default(); let mut introspector = introspect_html(&output, &mut link_targets); let mut root = root_element(output, &info)?; crate::link::identify_link_targets(&mut root, &mut introspector, link_targets); @@ -99,12 +99,12 @@ fn html_document_impl( #[typst_macros::time(name = "introspect html")] fn introspect_html( output: &[HtmlNode], - link_targets: &mut HashSet, + link_targets: &mut FxHashSet, ) -> Introspector { fn discover( builder: &mut IntrospectorBuilder, sink: &mut Vec<(Content, Position)>, - link_targets: &mut HashSet, + link_targets: &mut FxHashSet, nodes: &[HtmlNode], ) { for node in nodes { diff --git a/crates/typst-html/src/link.rs b/crates/typst-html/src/link.rs index ad70f06fe..58dd49cd3 100644 --- a/crates/typst-html/src/link.rs +++ b/crates/typst-html/src/link.rs @@ -1,7 +1,8 @@ -use std::collections::{HashMap, HashSet, VecDeque}; +use std::collections::VecDeque; use comemo::Track; use ecow::{EcoString, eco_format}; +use rustc_hash::{FxHashMap, FxHashSet}; use typst_library::foundations::{Label, NativeElement}; use typst_library::introspection::{Introspector, Location, Tag}; use typst_library::layout::{Frame, FrameItem, Point}; @@ -16,7 +17,7 @@ use crate::{HtmlElement, HtmlNode, attr, tag}; /// in favor of the query in `identify_link_targets`. For the time being, some /// links are created without existence of a `LinkElem`, so this is /// unfortunately necessary. -pub fn introspect_frame_links(frame: &Frame, targets: &mut HashSet) { +pub fn introspect_frame_links(frame: &Frame, targets: &mut FxHashSet) { for (_, item) in frame.items() { match item { FrameItem::Link(Destination::Location(loc), _) => { @@ -35,7 +36,7 @@ pub fn introspect_frame_links(frame: &Frame, targets: &mut HashSet) { pub fn identify_link_targets( root: &mut HtmlElement, introspector: &mut Introspector, - mut targets: HashSet, + mut targets: FxHashSet, ) { // Query for all links with an intra-doc (i.e. `Location`) destination to // know what needs IDs. @@ -72,7 +73,7 @@ pub fn identify_link_targets( /// Traverses a list of nodes. fn traverse( work: &mut Work, - targets: &HashSet, + targets: &FxHashSet, identificator: &mut Identificator<'_>, nodes: &mut Vec, ) { @@ -144,7 +145,7 @@ fn traverse( /// Traverses a frame embedded in HTML. fn traverse_frame( work: &mut Work, - targets: &HashSet, + targets: &FxHashSet, identificator: &mut Identificator<'_>, frame: &Frame, link_points: &mut Vec<(Point, EcoString)>, @@ -174,13 +175,13 @@ struct Work { /// now. queue: VecDeque<(Location, Option