Ver código fonte

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%
Brad Fitzpatrick 11 anos atrás
pai
commit
72a68649ba
2 arquivos alterados com 57 adições e 2 exclusões
  1. 18 2
      memcache/selector.go
  2. 39 0
      memcache/selector_test.go

+ 18 - 2
memcache/selector.go

@@ -86,13 +86,29 @@ func (ss *ServerList) Each(f func(net.Addr) error) error {
 	return nil
 }
 
+// keyBufPool returns []byte buffers for use by PickServer's call to
+// crc32.ChecksumIEEE to avoid allocations. (but doesn't avoid the
+// copies, which at least are bounded in size and small)
+var keyBufPool = sync.Pool{
+	New: func() interface{} {
+		b := make([]byte, 256)
+		return &b
+	},
+}
+
 func (ss *ServerList) PickServer(key string) (net.Addr, error) {
 	ss.mu.RLock()
 	defer ss.mu.RUnlock()
 	if len(ss.addrs) == 0 {
 		return nil, ErrNoServers
 	}
-	// TODO-GO: remove this copy
-	cs := crc32.ChecksumIEEE([]byte(key))
+	if len(ss.addrs) == 1 {
+		return ss.addrs[0], nil
+	}
+	bufp := keyBufPool.Get().(*[]byte)
+	n := copy(*bufp, key)
+	cs := crc32.ChecksumIEEE((*bufp)[:n])
+	keyBufPool.Put(bufp)
+
 	return ss.addrs[cs%uint32(len(ss.addrs))], nil
 }

+ 39 - 0
memcache/selector_test.go

@@ -0,0 +1,39 @@
+/*
+Copyright 2014 Google Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package memcache
+
+import "testing"
+
+func BenchmarkPickServer(b *testing.B) {
+	// at least two to avoid 0 and 1 special cases:
+	benchPickServer(b, "127.0.0.1:1234", "127.0.0.1:1235")
+}
+
+func BenchmarkPickServer_Single(b *testing.B) {
+	benchPickServer(b, "127.0.0.1:1234")
+}
+
+func benchPickServer(b *testing.B, servers ...string) {
+	b.ReportAllocs()
+	var ss ServerList
+	ss.SetServers(servers...)
+	for i := 0; i < b.N; i++ {
+		if _, err := ss.PickServer("some key"); err != nil {
+			b.Fatal(err)
+		}
+	}
+}