From 02b4117b70835dacc9ec564895bc2083f20b197d Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Tue, 9 Jan 2018 11:30:09 +0100 Subject: [PATCH] Parse smiley codes only once during the request lifetime The parsed smilies are already semi-immutable during the request lifetime and especially the ordering by lenght via `mb_strlen()` is an expensive operation. Using a static runtime cache improves the performance when rebuilding messages in bulk, reducing the time by up to 40%. We should backport this to 3.0 once it has proven to be stable, especially changing the `$smilies` property into a static variable can break derived classes. --- .../node/HtmlInputNodeTextParser.class.php | 70 ++++++++++--------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeTextParser.class.php b/wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeTextParser.class.php index 8ea4f1024e..5554dbc427 100644 --- a/wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeTextParser.class.php +++ b/wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeTextParser.class.php @@ -43,12 +43,6 @@ class HtmlInputNodeTextParser { */ protected $smileyCount = 0; - /** - * list of smilies by smiley code - * @var Smiley[] - */ - protected $smilies = []; - /** * @var string[] */ @@ -60,6 +54,12 @@ class HtmlInputNodeTextParser { */ protected static $illegalChars = '[^\x0-\x2C\x2E\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]+'; + /** + * list of smilies by smiley code + * @var Smiley[] + */ + protected static $smilies; + /** * regex for user mentions * @var string @@ -91,34 +91,40 @@ class HtmlInputNodeTextParser { if (MODULE_SMILEY) { $this->smileyCount = $smileyCount; - // get smilies - $smilies = SmileyCache::getInstance()->getSmilies(); - $categories = SmileyCache::getInstance()->getCategories(); - - foreach ($smilies as $categoryID => $categorySmilies) { - if (!array_key_exists($categoryID ?: null, $categories) || $categories[$categoryID ?: null]->isDisabled) continue; + if (self::$smilies === null) { + self::$smilies = []; - /** @var Smiley $smiley */ - foreach ($categorySmilies as $smiley) { - foreach ($smiley->smileyCodes as $smileyCode) { - $this->smilies[$smileyCode] = $smiley; - } - } - } - - uksort($this->smilies, function($a, $b) { - $lengthA = mb_strlen($a); - $lengthB = mb_strlen($b); + // get smilies + $smilies = SmileyCache::getInstance()->getSmilies(); + $categories = SmileyCache::getInstance()->getCategories(); - if ($lengthA < $lengthB) { - return 1; - } - else if ($lengthA === $lengthB) { - return 0; + foreach ($smilies as $categoryID => $categorySmilies) { + if (!array_key_exists($categoryID ?: null, $categories) || $categories[$categoryID ?: null]->isDisabled) continue; + + /** @var Smiley $smiley */ + foreach ($categorySmilies as $smiley) { + foreach ($smiley->smileyCodes as $smileyCode) { + self::$smilies[$smileyCode] = $smiley; + } + } } - return -1; - }); + uksort(self::$smilies, function ($a, $b) { + $lengthA = mb_strlen($a); + $lengthB = mb_strlen($b); + + if ($lengthA < $lengthB) { + return 1; + } + else { + if ($lengthA === $lengthB) { + return 0; + } + } + + return -1; + }); + } } } @@ -457,7 +463,7 @@ class HtmlInputNodeTextParser { 'difficult' => [] ]; - foreach ($this->smilies as $smileyCode => $smiley) { + foreach (self::$smilies as $smileyCode => $smiley) { $smileyCode = preg_quote($smileyCode, '~'); if (preg_match('~^\\\:.+\\\:$~', $smileyCode)) { @@ -544,7 +550,7 @@ class HtmlInputNodeTextParser { } $this->smileyCount++; - $smiley = $this->smilies[$smileyCode]; + $smiley = self::$smilies[$smileyCode]; $element = $text->ownerDocument->createElement('img'); $element->setAttribute('src', $smiley->getURL()); $element->setAttribute('class', 'smiley'); -- 2.20.1