Merge pull request #26 from dgryski/consistenthash-binary-search

consistenthash: replace linear search with binary search
This commit is contained in:
Brad Fitzpatrick 2014-07-02 13:37:02 -07:00
commit a531d51b7f
2 changed files with 31 additions and 7 deletions

View File

@ -69,13 +69,13 @@ func (m *Map) Get(key string) string {
hash := int(m.hash([]byte(key)))
// Linear search for appropriate replica.
for _, v := range m.keys {
if v >= hash {
return m.hashMap[v]
}
}
// Binary search for appropriate replica.
idx := sort.Search(len(m.keys), func(i int) bool { return m.keys[i] >= hash })
// Means we have cycled back to the first replica.
return m.hashMap[m.keys[0]]
if idx == len(m.keys) {
idx = 0
}
return m.hashMap[m.keys[idx]]
}

View File

@ -17,6 +17,7 @@ limitations under the License.
package consistenthash
import (
"fmt"
"strconv"
"testing"
)
@ -84,3 +85,26 @@ func TestConsistency(t *testing.T) {
}
}
func BenchmarkGet8(b *testing.B) { benchmarkGet(b, 8) }
func BenchmarkGet32(b *testing.B) { benchmarkGet(b, 32) }
func BenchmarkGet128(b *testing.B) { benchmarkGet(b, 128) }
func BenchmarkGet512(b *testing.B) { benchmarkGet(b, 512) }
func benchmarkGet(b *testing.B, shards int) {
hash := New(shards, nil)
var buckets []string
for i := 0; i < shards; i++ {
buckets = append(buckets, fmt.Sprintf("shard-%d", i))
}
hash.Add(buckets...)
b.ResetTimer()
for i := 0; i < b.N; i++ {
hash.Get(buckets[i&(shards-1)])
}
}