Browse Source

Merge pull request #4239 from naderman/memory-rules

Reduce memory usage of Rule objects
Jordi Boggiano 9 years ago
parent
commit
7e0db8aa46

+ 1 - 1
src/Composer/DependencyResolver/Problem.php

@@ -47,7 +47,7 @@ class Problem
      */
     public function addRule(Rule $rule)
     {
-        $this->addReason($rule->getId(), array(
+        $this->addReason(spl_object_hash($rule), array(
             'rule' => $rule,
             'job' => $rule->getJob(),
         ));

+ 22 - 31
src/Composer/DependencyResolver/Rule.php

@@ -29,33 +29,34 @@ class Rule
     const RULE_LEARNED = 12;
     const RULE_PACKAGE_ALIAS = 13;
 
+    const BITFIELD_TYPE = 0;
+    const BITFIELD_REASON = 8;
+    const BITFIELD_DISABLED = 16;
+
     /**
      * READ-ONLY: The literals this rule consists of.
      * @var array
      */
     public $literals;
 
-    protected $disabled;
-    protected $type;
-    protected $id;
-    protected $reason;
+    protected $bitfield;
     protected $reasonData;
 
-    protected $job;
-
     public function __construct(array $literals, $reason, $reasonData, $job = null)
     {
         // sort all packages ascending by id
         sort($literals);
 
         $this->literals = $literals;
-        $this->reason = $reason;
         $this->reasonData = $reasonData;
 
-        $this->disabled = false;
-        $this->job = $job;
-        $this->type = -1;
+        if ($job) {
+            $this->job = $job;
+        }
 
+        $this->bitfield = (0 << self::BITFIELD_DISABLED) |
+            ($reason << self::BITFIELD_REASON) |
+            (255 << self::BITFIELD_TYPE);
     }
 
     public function getHash()
@@ -64,24 +65,14 @@ class Rule
         return $data['hash'];
     }
 
-    public function setId($id)
-    {
-        $this->id = $id;
-    }
-
-    public function getId()
-    {
-        return $this->id;
-    }
-
     public function getJob()
     {
-        return $this->job;
+        return isset($this->job) ? $this->job : null;
     }
 
     public function getReason()
     {
-        return $this->reason;
+        return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON;
     }
 
     public function getReasonData()
@@ -91,11 +82,11 @@ class Rule
 
     public function getRequiredPackage()
     {
-        if ($this->reason === self::RULE_JOB_INSTALL) {
+        if ($this->getReason() === self::RULE_JOB_INSTALL) {
             return $this->reasonData;
         }
 
-        if ($this->reason === self::RULE_PACKAGE_REQUIRES) {
+        if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
             return $this->reasonData->getTarget();
         }
     }
@@ -125,32 +116,32 @@ class Rule
 
     public function setType($type)
     {
-        $this->type = $type;
+        $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE);
     }
 
     public function getType()
     {
-        return $this->type;
+        return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE;
     }
 
     public function disable()
     {
-        $this->disabled = true;
+        $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED);
     }
 
     public function enable()
     {
-        $this->disabled = false;
+        $this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_DISABLED);
     }
 
     public function isDisabled()
     {
-        return $this->disabled;
+        return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
     }
 
     public function isEnabled()
     {
-        return !$this->disabled;
+        return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
     }
 
     /**
@@ -176,7 +167,7 @@ class Rule
             $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
         }
 
-        switch ($this->reason) {
+        switch ($this->getReason()) {
             case self::RULE_INTERNAL_ALLOW_UPDATE:
                 return $ruleText;
 

+ 2 - 3
src/Composer/DependencyResolver/RuleSet.php

@@ -30,7 +30,7 @@ class RuleSet implements \IteratorAggregate, \Countable
     public $ruleById;
 
     protected static $types = array(
-        -1 => 'UNKNOWN',
+        255 => 'UNKNOWN',
         self::TYPE_PACKAGE => 'PACKAGE',
         self::TYPE_JOB => 'JOB',
         self::TYPE_LEARNED => 'LEARNED',
@@ -66,7 +66,6 @@ class RuleSet implements \IteratorAggregate, \Countable
         $this->ruleById[$this->nextRuleId] = $rule;
         $rule->setType($type);
 
-        $rule->setId($this->nextRuleId);
         $this->nextRuleId++;
 
         $hash = $rule->getHash();
@@ -131,7 +130,7 @@ class RuleSet implements \IteratorAggregate, \Countable
     public function getTypes()
     {
         $types = self::$types;
-        unset($types[-1]);
+        unset($types[255]);
 
         return array_keys($types);
     }

+ 3 - 3
src/Composer/DependencyResolver/Solver.php

@@ -319,7 +319,7 @@ class Solver
 
             $this->rules->add($newRule, RuleSet::TYPE_LEARNED);
 
-            $this->learnedWhy[$newRule->getId()] = $why;
+            $this->learnedWhy[spl_object_hash($newRule)] = $why;
 
             $ruleNode = new RuleWatchNode($newRule);
             $ruleNode->watch2OnHighest($this->decisions);
@@ -454,7 +454,7 @@ class Solver
 
     private function analyzeUnsolvableRule($problem, $conflictRule)
     {
-        $why = $conflictRule->getId();
+        $why = spl_object_hash($conflictRule);
 
         if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
             $learnedWhy = $this->learnedWhy[$why];
@@ -572,7 +572,7 @@ class Solver
     private function enableDisableLearnedRules()
     {
         foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) {
-            $why = $this->learnedWhy[$rule->getId()];
+            $why = $this->learnedWhy[spl_object_hash($rule)];
             $problemRules = $this->learnedPool[$why];
 
             $foundDisabled = false;

+ 3 - 10
tests/Composer/Test/DependencyResolver/RuleTest.php

@@ -13,6 +13,7 @@
 namespace Composer\Test\DependencyResolver;
 
 use Composer\DependencyResolver\Rule;
+use Composer\DependencyResolver\RuleSet;
 use Composer\DependencyResolver\Pool;
 use Composer\Repository\ArrayRepository;
 use Composer\TestCase;
@@ -34,14 +35,6 @@ class RuleTest extends TestCase
         $this->assertEquals($hash['hash'], $rule->getHash());
     }
 
-    public function testSetAndGetId()
-    {
-        $rule = new Rule(array(), 'job1', null);
-        $rule->setId(666);
-
-        $this->assertEquals(666, $rule->getId());
-    }
-
     public function testEqualsForRulesWithDifferentHashes()
     {
         $rule = new Rule(array(1, 2), 'job1', null);
@@ -69,9 +62,9 @@ class RuleTest extends TestCase
     public function testSetAndGetType()
     {
         $rule = new Rule(array(), 'job1', null);
-        $rule->setType('someType');
+        $rule->setType(RuleSet::TYPE_JOB);
 
-        $this->assertEquals('someType', $rule->getType());
+        $this->assertEquals(RuleSet::TYPE_JOB, $rule->getType());
     }
 
     public function testEnable()