-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce support for per-call memory allocator for caching
This change adds the ability to pass a memory allocator to caching methods via their context argument. This allows the underlying client to use memory allocators better suited to their workloads than GC. This is only used by the Memcached client at the moment. See grafana/mimir#3772 Signed-off-by: Nick Pillitteri <nick.pillitteri@grafana.com>
- Loading branch information
1 parent
356662f
commit 829f347
Showing
10 changed files
with
199 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package cache | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"net" | ||
"testing" | ||
"time" | ||
|
||
"github.com/go-kit/log" | ||
"github.com/grafana/gomemcache/memcache" | ||
"github.com/prometheus/client_golang/prometheus" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestMemcachedClient_GetMulti(t *testing.T) { | ||
setup := func() (*memcachedClient, *mockMemcachedClientBackend, error) { | ||
backend := newMockMemcachedClientBackend() | ||
client, err := newMemcachedClient( | ||
log.NewNopLogger(), | ||
backend, | ||
&mockServerSelector{}, | ||
MemcachedClientConfig{ | ||
Addresses: []string{"localhost"}, | ||
MaxAsyncConcurrency: 1, | ||
MaxAsyncBufferSize: 10, | ||
DNSProviderUpdateInterval: 10 * time.Second, | ||
}, | ||
prometheus.NewPedanticRegistry(), | ||
"test", | ||
) | ||
|
||
return client, backend, err | ||
} | ||
|
||
t.Run("no allocator", func(t *testing.T) { | ||
client, backend, err := setup() | ||
require.NoError(t, err) | ||
require.NoError(t, client.SetAsync(context.Background(), "foo", []byte("bar"), 10*time.Second)) | ||
require.NoError(t, client.wait()) | ||
|
||
ctx := context.Background() | ||
res := client.GetMulti(ctx, []string{"foo"}) | ||
require.Equal(t, map[string][]byte{"foo": []byte("bar")}, res) | ||
require.Equal(t, 0, backend.allocations) | ||
}) | ||
|
||
t.Run("with allocator", func(t *testing.T) { | ||
client, backend, err := setup() | ||
require.NoError(t, err) | ||
require.NoError(t, client.SetAsync(context.Background(), "foo", []byte("bar"), 10*time.Second)) | ||
require.NoError(t, client.wait()) | ||
|
||
ctx := WithAllocator(context.Background(), &nopAllocator{}) | ||
res := client.GetMulti(ctx, []string{"foo"}) | ||
require.Equal(t, map[string][]byte{"foo": []byte("bar")}, res) | ||
require.Equal(t, 1, backend.allocations) | ||
}) | ||
} | ||
|
||
type mockMemcachedClientBackend struct { | ||
allocations int | ||
values map[string]*memcache.Item | ||
} | ||
|
||
func newMockMemcachedClientBackend() *mockMemcachedClientBackend { | ||
return &mockMemcachedClientBackend{ | ||
values: make(map[string]*memcache.Item), | ||
} | ||
} | ||
|
||
func (m *mockMemcachedClientBackend) GetMulti(keys []string, opts ...memcache.Option) (map[string]*memcache.Item, error) { | ||
options := &memcache.Options{} | ||
for _, opt := range opts { | ||
opt(options) | ||
} | ||
|
||
if options.Alloc != nil { | ||
m.allocations += 1 | ||
} | ||
|
||
out := make(map[string]*memcache.Item) | ||
for _, k := range keys { | ||
if v, ok := m.values[k]; ok { | ||
out[k] = v | ||
} | ||
} | ||
|
||
return out, nil | ||
} | ||
|
||
func (m *mockMemcachedClientBackend) Set(item *memcache.Item) error { | ||
m.values[item.Key] = item | ||
return nil | ||
} | ||
|
||
func (m *mockMemcachedClientBackend) Delete(key string) error { | ||
delete(m.values, key) | ||
return nil | ||
} | ||
|
||
type mockServerSelector struct{} | ||
|
||
func (m mockServerSelector) SetServers(_ ...string) error { | ||
return nil | ||
} | ||
|
||
func (m mockServerSelector) PickServer(key string) (net.Addr, error) { | ||
return nil, errors.New("mock server selector") | ||
} | ||
|
||
func (m mockServerSelector) Each(f func(net.Addr) error) error { | ||
return nil | ||
} | ||
|
||
type nopAllocator struct{} | ||
|
||
func (n nopAllocator) Get(sz int) *[]byte { return nil } | ||
func (n nopAllocator) Put(b *[]byte) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters