make a global string interner
authorEh2406 <YeomanYaacov@gmail.com>
Sun, 4 Mar 2018 02:01:33 +0000 (21:01 -0500)
committerEh2406 <YeomanYaacov@gmail.com>
Tue, 6 Mar 2018 20:30:56 +0000 (15:30 -0500)
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
src/cargo/core/interning.rs [new file with mode: 0644]
src/cargo/core/mod.rs
src/cargo/core/resolver/mod.rs
src/cargo/lib.rs

index e7d52c3e56b7d76a1ee4e609feed718cd186ec28..477a044f688db5c6ad85bedc4b54e2d0f3c118af 100644 (file)
@@ -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 (file)
index 0000000..82b6830
--- /dev/null
@@ -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])
+    }
+}
index df1eff0725e5b1a9945cedfff36d7c7670634104..530683910524a62058d836b9e531f0bfd6056485 100644 (file)
@@ -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;
index 1ee360f40f50f7db28bfcefea10f4aaa3cceabdf..49537d676aba5cf22b12906f796be529d94e91cd 100644 (file)
@@ -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<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)],
@@ -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()));
@@ -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)
index abcdd3f4adca2f2d338a664a74eb44ab6b163549..5a5c39911664527c3f8349f2f192c5c947cc3289 100644 (file)
@@ -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;