Cache the query result.
authorEh2406 <YeomanYaacov@gmail.com>
Fri, 2 Mar 2018 22:56:36 +0000 (17:56 -0500)
committerEh2406 <YeomanYaacov@gmail.com>
Fri, 2 Mar 2018 22:56:36 +0000 (17:56 -0500)
In a test on https://github.com/rust-lang/cargo/issues/4810#issuecomment-357553286
Before we got to 1700000 ticks in ~97 sec
After we got to 1700000 ticks in ~92 sec
And query disappears from the flame graph

src/cargo/core/dependency.rs
src/cargo/core/resolver/mod.rs
src/cargo/util/cfg.rs

index aa24554e771d2363d406975d2760c2c2ba15208a..122f060eaac07114b2eebd1e5e5f3e0c30ee9986 100644 (file)
@@ -12,13 +12,13 @@ use util::errors::{CargoResult, CargoResultExt, CargoError};
 
 /// Information about a dependency requested by a Cargo manifest.
 /// Cheap to copy.
-#[derive(PartialEq, Clone, Debug)]
+#[derive(PartialEq, Eq, Ord, PartialOrd, Clone, Debug)]
 pub struct Dependency {
     inner: Rc<Inner>,
 }
 
 /// The data underlying a Dependency.
-#[derive(PartialEq, Clone, Debug)]
+#[derive(PartialEq, Eq, Ord, PartialOrd, Clone, Debug)]
 struct Inner {
     name: String,
     source_id: SourceId,
@@ -38,7 +38,7 @@ struct Inner {
     platform: Option<Platform>,
 }
 
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)]
 pub enum Platform {
     Name(String),
     Cfg(CfgExpr),
@@ -76,7 +76,7 @@ impl ser::Serialize for Dependency {
     }
 }
 
-#[derive(PartialEq, Clone, Debug, Copy)]
+#[derive(PartialEq, Eq, Ord, PartialOrd, Clone, Debug, Copy)]
 pub enum Kind {
     Normal,
     Development,
index 54e8517f4e8a4e17c0016022028a1a6eb7181520..44e9124d50c8bbf59bc3a9a3a70abbf63bc6a585 100644 (file)
@@ -1231,13 +1231,8 @@ impl<'a> Context<'a> {
         // Next, transform all dependencies into a list of possible candidates
         // which can satisfy that dependency.
         let mut deps = deps.into_iter().map(|(dep, features)| {
-            let mut candidates = self.query(registry, &dep)?;
-            // When we attempt versions for a package, we'll want to start at
-            // the maximum version and work our way down.
-            candidates.sort_by(|a, b| {
-                b.summary.version().cmp(a.summary.version())
-            });
-            Ok((dep, Rc::new(candidates), Rc::new(features)))
+            let candidates = self.query(registry, &dep)?;
+            Ok((dep, candidates, Rc::new(features)))
         }).collect::<CargoResult<Vec<DepInfo>>>()?;
 
         // Attempt to resolve dependencies with fewer candidates before trying
@@ -1257,7 +1252,13 @@ impl<'a> Context<'a> {
     /// return.
     fn query(&self,
              registry: &mut Registry,
-             dep: &Dependency) -> CargoResult<Vec<Candidate>> {
+             dep: &Dependency) -> CargoResult<Rc<Vec<Candidate>>> {
+        use ::std::cell::RefCell;
+        thread_local!(static CACHE: RefCell<BTreeMap<Dependency, Rc<Vec<Candidate>>>> = RefCell::new(BTreeMap::new()));
+        if let Some(out) = CACHE.with(|m| m.borrow().get(dep).cloned()) {
+            return Ok(out);
+        }
+
         let mut ret = Vec::new();
         registry.query(dep, &mut |s| {
             ret.push(Candidate { summary: s, replace: None });
@@ -1318,7 +1319,18 @@ impl<'a> Context<'a> {
 
             candidate.replace = replace;
         }
-        Ok(ret)
+
+        // When we attempt versions for a package, we'll want to start at
+        // the maximum version and work our way down.
+        ret.sort_unstable_by(|a, b| {
+            b.summary.version().cmp(a.summary.version())
+        });
+
+        let out = Rc::new(ret);
+
+        CACHE.with(|m| m.borrow_mut().insert(dep.clone(), out.clone()));
+
+        Ok(out)
     }
 
     fn prev_active(&self, dep: &Dependency) -> &[Summary] {
index 8307ef75ccdf57c84e441f1a57a71f910c871d65..847d00df1fe36d5ba7795202e7dd20ba61b492bb 100644 (file)
@@ -4,13 +4,13 @@ use std::fmt;
 
 use util::{CargoError, CargoResult};
 
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)]
 pub enum Cfg {
     Name(String),
     KeyPair(String, String),
 }
 
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug)]
 pub enum CfgExpr {
     Not(Box<CfgExpr>),
     All(Vec<CfgExpr>),