From 1f764c55484cb5ca4899a0b51385ae91177dd7d8 Mon Sep 17 00:00:00 2001 From: Eh2406 Date: Sat, 3 Mar 2018 21:01:33 -0500 Subject: [PATCH] make a global string interner In a test on https://github.com/rust-lang/cargo/issues/4810#issuecomment-357553286 Before we got to 5000000 ticks in ~72 sec After we got to 5000000 ticks in ~65 sec --- Cargo.toml | 1 + src/cargo/core/interning.rs | 34 ++++++++++++++++++++++++++++++++++ src/cargo/core/mod.rs | 1 + src/cargo/core/resolver/mod.rs | 9 +++++---- src/cargo/lib.rs | 1 + 5 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 src/cargo/core/interning.rs diff --git a/Cargo.toml b/Cargo.toml index e7d52c3e5..477a044f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ glob = "0.2" hex = "0.3" home = "0.3" ignore = "0.4" +lazy_static = "1.0.0" jobserver = "0.1.9" lazycell = "0.6" libc = "0.2" diff --git a/src/cargo/core/interning.rs b/src/cargo/core/interning.rs new file mode 100644 index 000000000..82b6830ee --- /dev/null +++ b/src/cargo/core/interning.rs @@ -0,0 +1,34 @@ +use std::fmt; +use std::sync::RwLock; +use std::collections::HashMap; + +lazy_static! { + static ref STRING_CASHE: RwLock<(Vec, HashMap)> = + RwLock::new((Vec::new(), HashMap::new())); +} + +#[derive(Eq, PartialEq, Hash, Clone, Copy)] +pub struct InternedString { + id: usize +} + +impl InternedString { + pub fn new(str: &str) -> InternedString { + let (ref mut str_from_id, ref mut id_from_str) = *STRING_CASHE.write().unwrap(); + if let Some(&id) = id_from_str.get(str) { + return InternedString { id }; + } + str_from_id.push(str.to_string()); + id_from_str.insert(str.to_string(), str_from_id.len() - 1); + return InternedString { id: str_from_id.len() - 1 } + } +// pub fn to_inner(&self) -> String { +// STRING_CASHE.read().unwrap().0[self.id].to_string() +// } +} + +impl fmt::Debug for InternedString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "InternedString {{ {} }}", STRING_CASHE.read().unwrap().0[self.id]) + } +} diff --git a/src/cargo/core/mod.rs b/src/cargo/core/mod.rs index df1eff072..530683910 100644 --- a/src/cargo/core/mod.rs +++ b/src/cargo/core/mod.rs @@ -21,6 +21,7 @@ pub mod resolver; pub mod summary; pub mod shell; pub mod registry; +mod interning; mod package_id_spec; mod workspace; mod features; diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index 1ee360f40..49537d676 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -60,6 +60,7 @@ use url::Url; use core::{PackageId, Registry, SourceId, Summary, Dependency}; use core::PackageIdSpec; +use core::interning::InternedString; use util::config::Config; use util::Graph; use util::errors::{CargoResult, CargoError}; @@ -344,7 +345,7 @@ struct Context { warnings: RcList, } -type Activations = HashMap>>>; +type Activations = HashMap>>>; /// Builds the list of all packages required to build the first argument. pub fn resolve(summaries: &[(Summary, Method)], @@ -1290,7 +1291,7 @@ impl Context { method: &Method) -> CargoResult { let id = summary.package_id(); let prev = self.activations - .entry(id.name().to_string()) + .entry(InternedString::new(id.name())) .or_insert_with(HashMap::new) .entry(id.source_id().clone()) .or_insert_with(||Rc::new(Vec::new())); @@ -1352,14 +1353,14 @@ impl Context { } fn prev_active(&self, dep: &Dependency) -> &[Summary] { - self.activations.get(dep.name()) + self.activations.get(&InternedString::new(dep.name())) .and_then(|v| v.get(dep.source_id())) .map(|v| &v[..]) .unwrap_or(&[]) } fn is_active(&self, id: &PackageId) -> bool { - self.activations.get(id.name()) + self.activations.get(&InternedString::new(id.name())) .and_then(|v| v.get(id.source_id())) .map(|v| v.iter().any(|s| s.package_id() == id)) .unwrap_or(false) diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index abcdd3f4a..5a5c39911 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -27,6 +27,7 @@ extern crate home; extern crate ignore; extern crate jobserver; extern crate lazycell; +#[macro_use] extern crate lazy_static; extern crate libc; extern crate libgit2_sys; extern crate num_cpus; -- 2.30.2