From 53968321999f3f4264373125c5ab2b61e7f972c1 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Thu, 20 Jun 2019 11:45:19 -0500 Subject: [PATCH] config: ServiceOptions O(1) assert time in the common case Check if the key array passed in the constructor is identical to the key array passed to assertRequiredOptions(). This takes O(1) time if the key arrays have the same underlying storage pointer, which is the common case. If the arrays have a different order but are otherwise identical, the slow path is taken instead. The comparison will add O(N) overhead in addition to the overhead of the array_diff() calls. Change-Id: Icb9040ab66286b72a270e84f910cb578bed105b0 --- includes/config/ServiceOptions.php | 31 ++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/includes/config/ServiceOptions.php b/includes/config/ServiceOptions.php index 0f3743f794..6ae059ebff 100644 --- a/includes/config/ServiceOptions.php +++ b/includes/config/ServiceOptions.php @@ -23,6 +23,7 @@ use Wikimedia\Assert\Assert; * @since 1.34 */ class ServiceOptions { + private $keys = []; private $options = []; /** @@ -33,6 +34,7 @@ class ServiceOptions { * @throws InvalidArgumentException if one of $keys is not found in any of $sources */ public function __construct( array $keys, ...$sources ) { + $this->keys = $keys; foreach ( $keys as $key ) { foreach ( $sources as $source ) { if ( $source instanceof Config ) { @@ -58,20 +60,21 @@ class ServiceOptions { * @param string[] $expectedKeys */ public function assertRequiredOptions( array $expectedKeys ) { - $actualKeys = array_keys( $this->options ); - $extraKeys = array_diff( $actualKeys, $expectedKeys ); - $missingKeys = array_diff( $expectedKeys, $actualKeys ); - Assert::precondition( !$extraKeys && !$missingKeys, - ( - $extraKeys - ? 'Unsupported options passed: ' . implode( ', ', $extraKeys ) . '!' - : '' - ) . ( $extraKeys && $missingKeys ? ' ' : '' ) . ( - $missingKeys - ? 'Required options missing: ' . implode( ', ', $missingKeys ) . '!' - : '' - ) - ); + if ( $this->keys !== $expectedKeys ) { + $extraKeys = array_diff( $this->keys, $expectedKeys ); + $missingKeys = array_diff( $expectedKeys, $this->keys ); + Assert::precondition( !$extraKeys && !$missingKeys, + ( + $extraKeys + ? 'Unsupported options passed: ' . implode( ', ', $extraKeys ) . '!' + : '' + ) . ( $extraKeys && $missingKeys ? ' ' : '' ) . ( + $missingKeys + ? 'Required options missing: ' . implode( ', ', $missingKeys ) . '!' + : '' + ) + ); + } } /** -- 2.20.1