From 93a2fdec953e596640eda3821c99c97027b59052 Mon Sep 17 00:00:00 2001 From: Andrey Legayev Date: Fri, 20 Mar 2020 01:07:26 +0200 Subject: [PATCH] ProcessExtends: Use map instead of list for selectors and parents * Convert Less\Tree\Extend#parent_ids from a list to a map. * Maintain a copy of Less\Tree\Selector#_oelements list in map form. Keep the list as well for now because there is a logical order to this information, which callers outside ProcessExtends depend on. These change bring an performance improvement. About 4% speedup for Magento2. Co-authored-by: Timo Tijhof --- lib/Less/Tree/Extend.php | 11 ++++++++--- lib/Less/Tree/Selector.php | 5 +++++ lib/Less/Visitor/processExtends.php | 10 ++++++---- test/index.php | 2 +- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/Less/Tree/Extend.php b/lib/Less/Tree/Extend.php index 8f21e939..c08a2a96 100644 --- a/lib/Less/Tree/Extend.php +++ b/lib/Less/Tree/Extend.php @@ -42,8 +42,13 @@ public function __construct($selector, $option, $index){ break; } - $this->object_id = $i++; - $this->parent_ids = array($this->object_id); + // This must use a string (instead of int) so that array_merge() + // preserves keys on arrays that use IDs in their keys. + $this->object_id = 'id_' . $i++; + + $this->parent_ids = array( + $this->object_id => true + ); } public function accept( $visitor ){ @@ -74,4 +79,4 @@ public function findSelfSelectors( $selectors ){ $this->selfSelectors = array(new Less_Tree_Selector($selfElements)); } -} \ No newline at end of file +} diff --git a/lib/Less/Tree/Selector.php b/lib/Less/Tree/Selector.php index 6b9dae61..6625fb8a 100644 --- a/lib/Less/Tree/Selector.php +++ b/lib/Less/Tree/Selector.php @@ -22,6 +22,7 @@ class Less_Tree_Selector extends Less_Tree{ public $elements_len = 0; public $_oelements; + public $_oelements_assoc; public $_oelements_len; public $cacheable = true; @@ -83,6 +84,8 @@ public function match( $other ){ public function CacheElements(){ $this->_oelements = array(); + $this->_oelements_assoc = array(); + $css = ''; foreach($this->elements as $v){ @@ -108,6 +111,8 @@ public function CacheElements(){ array_shift($this->_oelements); $this->_oelements_len--; } + + $this->_oelements_assoc = array_fill_keys($this->_oelements, true); } } diff --git a/lib/Less/Visitor/processExtends.php b/lib/Less/Visitor/processExtends.php index bb5f0824..3f779af5 100644 --- a/lib/Less/Visitor/processExtends.php +++ b/lib/Less/Visitor/processExtends.php @@ -53,8 +53,9 @@ private function doExtendChaining( $extendsList, $extendsListTarget, $iterationC $extend = $extendsList[$extendIndex]; $targetExtend = $extendsListTarget[$targetExtendIndex]; - // look for circular references - if( in_array($targetExtend->object_id, $extend->parent_ids,true) ){ + // Optimisation: Explicit reference,  + if( \array_key_exists($targetExtend->object_id, $extend->parent_ids) ){ + // ignore circular references continue; } @@ -269,7 +270,8 @@ private function HasMatches($extend, $haystackSelectorPath){ return true; } - if( in_array($first_el, $hackstackSelector->_oelements) ){ + // Optimisation: Explicit reference,  + if( \array_key_exists($first_el, $hackstackSelector->_oelements_assoc) ){ return true; } } @@ -466,4 +468,4 @@ protected function visitDirectiveOut(){ array_pop($this->allExtendsStack); } -} \ No newline at end of file +} diff --git a/test/index.php b/test/index.php index 2545f18c..fd76c640 100644 --- a/test/index.php +++ b/test/index.php @@ -690,7 +690,7 @@ function obj($mixed, $objects = array() ) { $exclude_keys = array('originalRuleset','currentFileInfo','lookups','index','ruleset_id','type','_rulesets','_variables','allowImports','_css','cache_string','elements_len', - '_oelements','first_oelements','_oelements_len','cacheable', ); //'variable','combinator' + '_oelements','_oelements_assoc','first_oelements','_oelements_len','cacheable', ); //'variable','combinator' //$exclude_keys = array(); $type = gettype($mixed);