Skip to content

Commit

Permalink
make a global string interner
Browse files Browse the repository at this point in the history
In a test on rust-lang#4810 (comment)
Before we got to 5000000 ticks in ~72 sec
After we got to 5000000 ticks in ~65 sec
  • Loading branch information
Eh2406 committed Mar 6, 2018
1 parent c721937 commit 1f764c5
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 4 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
34 changes: 34 additions & 0 deletions src/cargo/core/interning.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use std::fmt;
use std::sync::RwLock;
use std::collections::HashMap;

lazy_static! {
static ref STRING_CASHE: RwLock<(Vec<String>, HashMap<String, usize>)> =
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])
}
}
1 change: 1 addition & 0 deletions src/cargo/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
9 changes: 5 additions & 4 deletions src/cargo/core/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -344,7 +345,7 @@ struct Context {
warnings: RcList<String>,
}

type Activations = HashMap<String, HashMap<SourceId, Rc<Vec<Summary>>>>;
type Activations = HashMap<InternedString, HashMap<SourceId, Rc<Vec<Summary>>>>;

/// Builds the list of all packages required to build the first argument.
pub fn resolve(summaries: &[(Summary, Method)],
Expand Down Expand Up @@ -1290,7 +1291,7 @@ impl Context {
method: &Method) -> CargoResult<bool> {
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()));
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions src/cargo/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 1f764c5

Please sign in to comment.