Merge pull request #2819 from PHPOffice/Performance-Coordinates

Performance tweaks to calculating column string from index
This commit is contained in:
Mark Baker 2022-05-10 12:51:14 +02:00 committed by GitHub
commit 32efe0ee45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 21 additions and 14 deletions

View File

@ -276,35 +276,42 @@ abstract class Coordinate
if (isset($indexCache[$columnAddress])) { if (isset($indexCache[$columnAddress])) {
return $indexCache[$columnAddress]; return $indexCache[$columnAddress];
} }
// It's surprising how costly the strtoupper() and ord() calls actually are, so we use a lookup array rather than use ord() // It's surprising how costly the strtoupper() and ord() calls actually are, so we use a lookup array
// and make it case insensitive to get rid of the strtoupper() as well. Because it's a static, there's no significant // rather than use ord() and make it case insensitive to get rid of the strtoupper() as well.
// memory overhead either // Because it's a static, there's no significant memory overhead either.
static $columnLookup = [ static $columnLookup = [
'A' => 1, 'B' => 2, 'C' => 3, 'D' => 4, 'E' => 5, 'F' => 6, 'G' => 7, 'H' => 8, 'I' => 9, 'J' => 10, 'K' => 11, 'L' => 12, 'M' => 13, 'A' => 1, 'B' => 2, 'C' => 3, 'D' => 4, 'E' => 5, 'F' => 6, 'G' => 7, 'H' => 8, 'I' => 9, 'J' => 10,
'N' => 14, 'O' => 15, 'P' => 16, 'Q' => 17, 'R' => 18, 'S' => 19, 'T' => 20, 'U' => 21, 'V' => 22, 'W' => 23, 'X' => 24, 'Y' => 25, 'Z' => 26, 'K' => 11, 'L' => 12, 'M' => 13, 'N' => 14, 'O' => 15, 'P' => 16, 'Q' => 17, 'R' => 18, 'S' => 19,
'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5, 'f' => 6, 'g' => 7, 'h' => 8, 'i' => 9, 'j' => 10, 'k' => 11, 'l' => 12, 'm' => 13, 'T' => 20, 'U' => 21, 'V' => 22, 'W' => 23, 'X' => 24, 'Y' => 25, 'Z' => 26,
'n' => 14, 'o' => 15, 'p' => 16, 'q' => 17, 'r' => 18, 's' => 19, 't' => 20, 'u' => 21, 'v' => 22, 'w' => 23, 'x' => 24, 'y' => 25, 'z' => 26, 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5, 'f' => 6, 'g' => 7, 'h' => 8, 'i' => 9, 'j' => 10,
'k' => 11, 'l' => 12, 'm' => 13, 'n' => 14, 'o' => 15, 'p' => 16, 'q' => 17, 'r' => 18, 's' => 19,
't' => 20, 'u' => 21, 'v' => 22, 'w' => 23, 'x' => 24, 'y' => 25, 'z' => 26,
]; ];
// We also use the language construct isset() rather than the more costly strlen() function to match the length of $columnAddress // We also use the language construct isset() rather than the more costly strlen() function to match the
// for improved performance // length of $columnAddress for improved performance
if (isset($columnAddress[0])) { if (isset($columnAddress[0])) {
if (!isset($columnAddress[1])) { if (!isset($columnAddress[1])) {
$indexCache[$columnAddress] = $columnLookup[$columnAddress]; $indexCache[$columnAddress] = $columnLookup[$columnAddress];
return $indexCache[$columnAddress]; return $indexCache[$columnAddress];
} elseif (!isset($columnAddress[2])) { } elseif (!isset($columnAddress[2])) {
$indexCache[$columnAddress] = $columnLookup[$columnAddress[0]] * 26 + $columnLookup[$columnAddress[1]]; $indexCache[$columnAddress] = $columnLookup[$columnAddress[0]] * 26
+ $columnLookup[$columnAddress[1]];
return $indexCache[$columnAddress]; return $indexCache[$columnAddress];
} elseif (!isset($columnAddress[3])) { } elseif (!isset($columnAddress[3])) {
$indexCache[$columnAddress] = $columnLookup[$columnAddress[0]] * 676 + $columnLookup[$columnAddress[1]] * 26 + $columnLookup[$columnAddress[2]]; $indexCache[$columnAddress] = $columnLookup[$columnAddress[0]] * 676
+ $columnLookup[$columnAddress[1]] * 26
+ $columnLookup[$columnAddress[2]];
return $indexCache[$columnAddress]; return $indexCache[$columnAddress];
} }
} }
throw new Exception('Column string index can not be ' . ((isset($columnAddress[0])) ? 'longer than 3 characters' : 'empty')); throw new Exception(
'Column string index can not be ' . ((isset($columnAddress[0])) ? 'longer than 3 characters' : 'empty')
);
} }
/** /**
@ -320,11 +327,11 @@ abstract class Coordinate
if (!isset($indexCache[$columnIndex])) { if (!isset($indexCache[$columnIndex])) {
$indexValue = $columnIndex; $indexValue = $columnIndex;
$base26 = null; $base26 = '';
do { do {
$characterValue = ($indexValue % 26) ?: 26; $characterValue = ($indexValue % 26) ?: 26;
$indexValue = ($indexValue - $characterValue) / 26; $indexValue = ($indexValue - $characterValue) / 26;
$base26 = chr($characterValue + 64) . ($base26 ?: ''); $base26 = chr($characterValue + 64) . $base26;
} while ($indexValue > 0); } while ($indexValue > 0);
$indexCache[$columnIndex] = $base26; $indexCache[$columnIndex] = $base26;
} }