Skip to content

Commit

Permalink
perf: use a faster hasher in compiler and LSP
Browse files Browse the repository at this point in the history
By applying the same hasher as in Rust's compiler, performance can be
improved wherever a hash map or set is used.

This currently has the most visible impact on the compiler's validation
step as it internally makes heavy use of hash maps.
  • Loading branch information
dnaka91 committed Jan 22, 2024
1 parent 359f02f commit 4eb37aa
Show file tree
Hide file tree
Showing 10 changed files with 42 additions and 22 deletions.
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ miette = "5.10.0"
mimalloc = "0.1.39"
proc-macro2 = { version = "1.0.76", default-features = false }
quote = { version = "1.0.35", default-features = false }
rustc-hash = "1.1.0"
serde = { version = "1.0.195", features = ["derive"] }
serde_json = "1.0.111"
syn = "2.0.48"
Expand Down
1 change: 1 addition & 0 deletions crates/mabo-compiler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ anstream.workspace = true
anstyle.workspace = true
mabo-parser = { path = "../mabo-parser" }
miette.workspace = true
rustc-hash.workspace = true
schemars = { version = "0.8.16", optional = true }
serde = { workspace = true, optional = true }
serde_json = { workspace = true, optional = true }
Expand Down
7 changes: 3 additions & 4 deletions crates/mabo-compiler/src/resolve/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
//! Ensure all referenced types within a schema itself, aswell as between schemas exist and are
//! correct.

use std::collections::HashMap;

use mabo_parser::{
DataType, Definition, ExternalType, Fields, Generics, Import, Name, Schema, Spanned, Type,
};
use miette::NamedSource;
use rustc_hash::FxHashMap;

pub use self::error::{
Error, GenericsCount, InvalidKind, MissingDefinition, MissingImport, MissingModule,
Expand Down Expand Up @@ -83,7 +82,7 @@ pub(crate) struct Module<'a> {
/// List of types that are declared in this module.
types: Vec<Declaration<'a>>,
/// Direct submodules located in this module.
modules: HashMap<&'a str, Module<'a>>,
modules: FxHashMap<&'a str, Module<'a>>,
/// List of original definitions.
definitions: &'a [Definition<'a>],
}
Expand Down Expand Up @@ -411,7 +410,7 @@ fn visit_module_tree<'a>(
path,
imports: Vec::new(),
types: Vec::new(),
modules: HashMap::new(),
modules: FxHashMap::default(),
definitions: defs,
};

Expand Down
12 changes: 7 additions & 5 deletions crates/mabo-compiler/src/validate/generics.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::{collections::HashMap, ops::Range};
use std::{hash::BuildHasherDefault, ops::Range};

use mabo_parser::{DataType, Enum, ExternalType, Fields, Generics, Span, Spanned, Struct, Type};
use miette::Diagnostic;
use rustc_hash::FxHashMap;
use thiserror::Error;

/// Generic type parameters are considered invalid.
Expand Down Expand Up @@ -53,7 +54,7 @@ pub fn validate_struct_generics(value: &Struct<'_>) -> Result<(), InvalidGeneric
.0
.iter()
.map(|gen| (gen.get(), gen.span()))
.collect::<HashMap<_, _>>();
.collect::<FxHashMap<_, _>>();

validate_field_generics(&value.fields, &mut unvisited);

Expand All @@ -75,7 +76,7 @@ pub fn validate_enum_generics(value: &Enum<'_>) -> Result<(), InvalidGenericType
.0
.iter()
.map(|gen| (gen.get(), gen.span()))
.collect::<HashMap<_, _>>();
.collect::<FxHashMap<_, _>>();

for variant in &value.variants {
validate_field_generics(&variant.fields, &mut unvisited);
Expand All @@ -92,7 +93,8 @@ pub fn validate_enum_generics(value: &Enum<'_>) -> Result<(), InvalidGenericType

/// Ensure all generic type arguments are unique within a struct or enum.
fn validate_duplicate_generics(value: &Generics<'_>) -> Result<(), DuplicateGenericName> {
let mut visited = HashMap::with_capacity(value.0.len());
let mut visited =
FxHashMap::with_capacity_and_hasher(value.0.len(), BuildHasherDefault::default());
value
.0
.iter()
Expand All @@ -110,7 +112,7 @@ fn validate_duplicate_generics(value: &Generics<'_>) -> Result<(), DuplicateGene

/// Iterate over all the fields and mark any generic types as used when disvored as type for a
/// field.
fn validate_field_generics(value: &Fields<'_>, unvisited: &mut HashMap<&str, Span>) {
fn validate_field_generics(value: &Fields<'_>, unvisited: &mut FxHashMap<&str, Span>) {
match &value {
Fields::Named(named) => {
for field in named {
Expand Down
12 changes: 8 additions & 4 deletions crates/mabo-compiler/src/validate/ids.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::{collections::HashMap, ops::Range};
use std::{hash::BuildHasherDefault, ops::Range};

use mabo_parser::{Enum, Fields, Id, Spanned, Struct};
use miette::Diagnostic;
use rustc_hash::FxHashMap;
use thiserror::Error;

use crate::IdGenerator;
Expand Down Expand Up @@ -97,7 +98,8 @@ pub(crate) fn validate_struct_ids(value: &Struct<'_>) -> Result<(), DuplicateFie
/// Ensure all IDs inside an enum are unique, which means all variants have a unique ID, plus all
/// potential fields in a variant are unique (within that variant).
pub(crate) fn validate_enum_ids(value: &Enum<'_>) -> Result<(), DuplicateId> {
let mut visited = HashMap::with_capacity(value.variants.len());
let mut visited =
FxHashMap::with_capacity_and_hasher(value.variants.len(), BuildHasherDefault::default());
let mut id_gen = IdGenerator::new();

value
Expand Down Expand Up @@ -131,7 +133,8 @@ pub(crate) fn validate_enum_ids(value: &Enum<'_>) -> Result<(), DuplicateId> {
fn validate_field_ids(value: &Fields<'_>) -> Result<(), DuplicateFieldId> {
match value {
Fields::Named(named) => {
let mut visited = HashMap::with_capacity(named.len());
let mut visited =
FxHashMap::with_capacity_and_hasher(named.len(), BuildHasherDefault::default());
let mut id_gen = IdGenerator::new();

named
Expand All @@ -152,7 +155,8 @@ fn validate_field_ids(value: &Fields<'_>) -> Result<(), DuplicateFieldId> {
.map_or(Ok(()), Err)?;
}
Fields::Unnamed(unnamed) => {
let mut visited = HashMap::with_capacity(unnamed.len());
let mut visited =
FxHashMap::with_capacity_and_hasher(unnamed.len(), BuildHasherDefault::default());
let mut id_gen = IdGenerator::new();

unnamed
Expand Down
12 changes: 8 additions & 4 deletions crates/mabo-compiler/src/validate/names.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::{collections::HashMap, ops::Range};
use std::{hash::BuildHasherDefault, ops::Range};

use mabo_parser::{Definition, Enum, Fields, Import, Spanned, Struct};
use miette::Diagnostic;
use rustc_hash::FxHashMap;
use thiserror::Error;

/// Duplicate name was encountered for two elements in the same scope.
Expand Down Expand Up @@ -76,7 +77,8 @@ pub(crate) fn validate_struct_names(value: &Struct<'_>) -> Result<(), DuplicateF
/// Ensure all names inside an enum are unique, which means all variants have a unique name, plus
/// all potential fields in a variant are unique (within that variant).
pub(crate) fn validate_enum_names(value: &Enum<'_>) -> Result<(), DuplicateName> {
let mut visited = HashMap::with_capacity(value.variants.len());
let mut visited =
FxHashMap::with_capacity_and_hasher(value.variants.len(), BuildHasherDefault::default());
value
.variants
.iter()
Expand Down Expand Up @@ -104,7 +106,8 @@ pub(crate) fn validate_enum_names(value: &Enum<'_>) -> Result<(), DuplicateName>
fn validate_field_names(value: &Fields<'_>) -> Result<(), DuplicateFieldName> {
match value {
Fields::Named(named) => {
let mut visited = HashMap::with_capacity(named.len());
let mut visited =
FxHashMap::with_capacity_and_hasher(named.len(), BuildHasherDefault::default());
named
.iter()
.find_map(|field| {
Expand All @@ -125,7 +128,8 @@ fn validate_field_names(value: &Fields<'_>) -> Result<(), DuplicateFieldName> {
}

pub(crate) fn validate_names_in_module(value: &[Definition<'_>]) -> Result<(), DuplicateName> {
let mut visited = HashMap::with_capacity(value.len());
let mut visited =
FxHashMap::with_capacity_and_hasher(value.len(), BuildHasherDefault::default());
value
.iter()
.find_map(|definition| {
Expand Down
1 change: 1 addition & 0 deletions crates/mabo-lsp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ mabo-project = { path = "../mabo-project" }
ouroboros = "0.18.2"
parking_lot = "0.12.1"
ropey = "1.6.1"
rustc-hash.workspace = true
serde_json.workspace = true
serde.workspace = true
time = { version = "0.3.31", features = ["formatting", "local-offset", "macros"] }
Expand Down
5 changes: 3 additions & 2 deletions crates/mabo-lsp/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#![warn(clippy::expect_used, clippy::unwrap_used)]

use std::{collections::HashMap, net::Ipv4Addr, time::Instant};
use std::{net::Ipv4Addr, time::Instant};

use anyhow::{bail, Result};
use log::{as_debug, debug, error, info, warn};
Expand All @@ -18,6 +18,7 @@ use lsp_types::{
},
DocumentSymbol, InitializeParams, SemanticTokens,
};
use rustc_hash::FxHashMap;

use self::{cli::Cli, client::Client};
use crate::state::GlobalState;
Expand Down Expand Up @@ -45,7 +46,7 @@ fn main() -> Result<()> {

let mut state = GlobalState {
client: Client::new(&connection),
files: HashMap::default(),
files: FxHashMap::default(),
settings: config::Global::default(),
};

Expand Down
5 changes: 2 additions & 3 deletions crates/mabo-lsp/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
use std::collections::HashMap;

use anyhow::{ensure, Context, Result};
use line_index::LineIndex;
use log::{as_debug, debug};
use lsp_types::{ConfigurationItem, Diagnostic, Url};
use mabo_parser::Schema;
use ouroboros::self_referencing;
use ropey::Rope;
use rustc_hash::FxHashMap;

use crate::{client::Client, config};

#[allow(clippy::module_name_repetitions)]
pub struct GlobalState<'a> {
pub client: Client<'a>,
pub files: HashMap<Url, File>,
pub files: FxHashMap<Url, File>,
pub settings: config::Global,
}

Expand Down

0 comments on commit 4eb37aa

Please sign in to comment.