From 44c330aa5d392e91d4261c6f2e142932a2a26884 Mon Sep 17 00:00:00 2001 From: Robin McCorkell Date: Tue, 20 Jan 2015 12:40:18 +0000 Subject: [PATCH] Performance improvements for NaturalSort A combination of using isset() instead of count() or strlen(), caching the chunkify function, and replacing is_numeric() with some comparisons --- lib/private/naturalsort.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/private/naturalsort.php b/lib/private/naturalsort.php index 6e259630f7..d511bfa3f6 100644 --- a/lib/private/naturalsort.php +++ b/lib/private/naturalsort.php @@ -12,6 +12,7 @@ namespace OC; class NaturalSort { private static $instance; private $collator; + private $cache = array(); /** * Split the given string in chunks of numbers and strings @@ -21,13 +22,15 @@ class NaturalSort { private function naturalSortChunkify($t) { // Adapted and ported to PHP from // http://my.opera.com/GreyWyvern/blog/show.dml/1671288 + if (isset($this->cache[$t])) { + return $this->cache[$t]; + } $tz = array(); $x = 0; $y = -1; $n = null; - $length = strlen($t); - while ($x < $length) { + while (isset($t[$x])) { $c = $t[$x]; // only include the dot in strings $m = ((!$n && $c === '.') || ($c >= '0' && $c <= '9')); @@ -40,6 +43,7 @@ class NaturalSort { $tz[$y] .= $c; $x++; } + $this->cache[$t] = $tz; return $tz; } @@ -75,14 +79,13 @@ class NaturalSort { // instead of ["test.txt", "test (2).txt"] $aa = self::naturalSortChunkify($a); $bb = self::naturalSortChunkify($b); - $alen = count($aa); - $blen = count($bb); - for ($x = 0; $x < $alen && $x < $blen; $x++) { + for ($x = 0; isset($aa[$x]) && isset($bb[$x]); $x++) { $aChunk = $aa[$x]; $bChunk = $bb[$x]; if ($aChunk !== $bChunk) { - if (is_numeric($aChunk) && is_numeric($bChunk)) { + // test first character (character comparison, not number comparison) + if ($aChunk[0] >= '0' && $aChunk[0] <= '9' && $bChunk[0] >= '0' && $bChunk[0] <= '9') { $aNum = (int)$aChunk; $bNum = (int)$bChunk; return $aNum - $bNum; @@ -90,7 +93,7 @@ class NaturalSort { return self::getCollator()->compare($aChunk, $bChunk); } } - return $alen - $blen; + return count($aa) - count($bb); } /**