فهرست منبع

Compute rule hashes for faster duplicate detection

Nils Adermann 13 سال پیش
والد
کامیت
40b33914b3

+ 14 - 1
src/Composer/DependencyResolver/Rule.php

@@ -45,6 +45,15 @@ class Rule
         $this->watch2 = (count($this->literals) > 1) ? $literals[1]->getId() : 0;
 
         $this->type = -1;
+
+        $this->ruleHash = substr(md5(implode(',', array_map(function ($l) {
+            return $l->getId();
+        }, $this->literals))), 0, 5);
+    }
+
+    public function getHash()
+    {
+        return $this->ruleHash;
     }
 
     public function setId($id)
@@ -67,12 +76,16 @@ class Rule
      */
     public function equals(Rule $rule)
     {
+        if ($this->ruleHash !== $rule->ruleHash) {
+            return false;
+        }
+
         if (count($this->literals) != count($rule->literals)) {
             return false;
         }
 
         for ($i = 0, $n = count($this->literals); $i < $n; $i++) {
-            if (!$this->literals[$i]->equals($rule->literals[$i])) {
+            if (!$this->literals[$i]->getId() === $rule->literals[$i]->getId()) {
                 return false;
             }
         }

+ 25 - 0
src/Composer/DependencyResolver/RuleSet.php

@@ -39,6 +39,8 @@ class RuleSet implements \IteratorAggregate, \Countable
     protected $ruleById;
     protected $nextRuleId;
 
+    protected $rulesByHash;
+
     public function __construct()
     {
         $this->nextRuleId = 0;
@@ -46,6 +48,8 @@ class RuleSet implements \IteratorAggregate, \Countable
         foreach ($this->getTypes() as $type) {
             $this->rules[$type] = array();
         }
+
+        $this->rulesByHash = array();
     }
 
     public function add(Rule $rule, $type)
@@ -64,6 +68,13 @@ class RuleSet implements \IteratorAggregate, \Countable
 
         $rule->setId($this->nextRuleId);
         $this->nextRuleId++;
+
+        $hash = $rule->getHash();
+        if (!isset($this->rulesByHash[$hash])) {
+            $this->rulesByHash[$hash] = array($rule);
+        } else {
+            $this->rulesByHash[$hash][] = $rule;
+        }
     }
 
     public function count()
@@ -129,6 +140,20 @@ class RuleSet implements \IteratorAggregate, \Countable
         return array_keys($types);
     }
 
+    public function containsEqual($rule)
+    {
+        if (isset($this->rulesByHash[$rule->getHash()])) {
+            $potentialDuplicates = $this->rulesByHash[$rule->getHash()];
+            foreach ($potentialDuplicates as $potentialDuplicate) {
+                if ($rule->equals($potentialDuplicate)) {
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
     public function __toString()
     {
         $string = "\n";

+ 2 - 4
src/Composer/DependencyResolver/Solver.php

@@ -229,10 +229,8 @@ class Solver
      */
     private function addRule($type, Rule $newRule = null) {
         if ($newRule) {
-            foreach ($this->rules->getIterator() as $rule) {
-                if ($rule->equals($newRule)) {
-                    return;
-                }
+            if ($this->rules->containsEqual($newRule)) {
+                return;
             }
 
             $this->rules->add($newRule, $type);