Skip to content

Commit 72a6864

Browse files
committed
Address an allocation TODO in the default ServerSelector.
And add a special case for only 1 server. Minor win, in any case. benchmark old ns/op new ns/op delta BenchmarkPickServer 262 234 -10.69% BenchmarkPickServer_Single 253 139 -45.06% benchmark old allocs new allocs delta BenchmarkPickServer 1 0 -100.00% BenchmarkPickServer_Single 1 0 -100.00% benchmark old bytes new bytes delta BenchmarkPickServer 8 0 -100.00% BenchmarkPickServer_Single 8 0 -100.00%
1 parent 19812ca commit 72a6864

2 files changed

Lines changed: 57 additions & 2 deletions

File tree

memcache/selector.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,29 @@ func (ss *ServerList) Each(f func(net.Addr) error) error {
8686
return nil
8787
}
8888

89+
// keyBufPool returns []byte buffers for use by PickServer's call to
90+
// crc32.ChecksumIEEE to avoid allocations. (but doesn't avoid the
91+
// copies, which at least are bounded in size and small)
92+
var keyBufPool = sync.Pool{
93+
New: func() interface{} {
94+
b := make([]byte, 256)
95+
return &b
96+
},
97+
}
98+
8999
func (ss *ServerList) PickServer(key string) (net.Addr, error) {
90100
ss.mu.RLock()
91101
defer ss.mu.RUnlock()
92102
if len(ss.addrs) == 0 {
93103
return nil, ErrNoServers
94104
}
95-
// TODO-GO: remove this copy
96-
cs := crc32.ChecksumIEEE([]byte(key))
105+
if len(ss.addrs) == 1 {
106+
return ss.addrs[0], nil
107+
}
108+
bufp := keyBufPool.Get().(*[]byte)
109+
n := copy(*bufp, key)
110+
cs := crc32.ChecksumIEEE((*bufp)[:n])
111+
keyBufPool.Put(bufp)
112+
97113
return ss.addrs[cs%uint32(len(ss.addrs))], nil
98114
}

memcache/selector_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
Copyright 2014 Google Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package memcache
18+
19+
import "testing"
20+
21+
func BenchmarkPickServer(b *testing.B) {
22+
// at least two to avoid 0 and 1 special cases:
23+
benchPickServer(b, "127.0.0.1:1234", "127.0.0.1:1235")
24+
}
25+
26+
func BenchmarkPickServer_Single(b *testing.B) {
27+
benchPickServer(b, "127.0.0.1:1234")
28+
}
29+
30+
func benchPickServer(b *testing.B, servers ...string) {
31+
b.ReportAllocs()
32+
var ss ServerList
33+
ss.SetServers(servers...)
34+
for i := 0; i < b.N; i++ {
35+
if _, err := ss.PickServer("some key"); err != nil {
36+
b.Fatal(err)
37+
}
38+
}
39+
}

0 commit comments

Comments
 (0)