From cfff40e900f5878e62d818985d8049357eccf099 Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Thu, 29 Aug 2019 19:24:53 -0700 Subject: [PATCH] Optimize HashRing to avoid hashing for the common single-location case Change-Id: I3423ac8bd5c56db60630257ac04706838a832d36 --- includes/libs/HashRing.php | 6 +++++ tests/phpunit/includes/libs/HashRingTest.php | 26 ++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/includes/libs/HashRing.php b/includes/libs/HashRing.php index f8ab6a3d89..94413c2be5 100644 --- a/includes/libs/HashRing.php +++ b/includes/libs/HashRing.php @@ -129,6 +129,12 @@ class HashRing implements Serializable { throw new InvalidArgumentException( "Invalid ring source specified." ); } + // Short-circuit for the common single-location case. Note that if there was only one + // location and it was ejected from the live ring, getLiveRing() would have error out. + if ( count( $this->weightByLocation ) == 1 ) { + return ( $limit > 0 ) ? [ $ring[0][self::KEY_LOCATION] ] : []; + } + // Locate the node index for this item's position on the hash ring $itemIndex = $this->findNodeIndexForPosition( $this->getItemPosition( $item ), $ring ); diff --git a/tests/phpunit/includes/libs/HashRingTest.php b/tests/phpunit/includes/libs/HashRingTest.php index 4afe3b56d5..8ddb7c9960 100644 --- a/tests/phpunit/includes/libs/HashRingTest.php +++ b/tests/phpunit/includes/libs/HashRingTest.php @@ -24,6 +24,32 @@ class HashRingTest extends PHPUnit\Framework\TestCase { } } + public function testHashRingSingleLocation() { + // SHA-1 based and weighted + $ring = new HashRing( [ 's1' => 1 ], 'sha1' ); + + $this->assertEquals( + [ 's1' => 1 ], + $ring->getLocationWeights(), + 'Normalized location weights' + ); + + for ( $i = 0; $i < 5; $i++ ) { + $this->assertEquals( + 's1', + $ring->getLocation( "hello$i" ), + 'Items placed at proper locations' + ); + $this->assertEquals( + [ 's1' ], + $ring->getLocations( "hello$i", 2 ), + 'Items placed at proper locations' + ); + } + + $this->assertEquals( [], $ring->getLocations( "helloX", 0 ), "Limit of 0" ); + } + public function testHashRingMapping() { // SHA-1 based and weighted $ring = new HashRing( -- 2.20.1