Skip to content

Commit 6fad3c1

Browse files
committed
[cache] optimize Redis implementation
1 parent a74d41f commit 6fad3c1

File tree

3 files changed

+29
-19
lines changed

3 files changed

+29
-19
lines changed

internal/sms-gateway/cache/factory.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ const (
1515
type Cache = cache.Cache
1616

1717
type Factory interface {
18-
New(name string) (cache.Cache, error)
18+
New(name string) (Cache, error)
1919
}
2020

2121
type factory struct {
22-
new func(name string) (cache.Cache, error)
22+
new func(name string) (Cache, error)
2323
}
2424

2525
func NewFactory(config Config) (Factory, error) {
@@ -35,7 +35,7 @@ func NewFactory(config Config) (Factory, error) {
3535
switch u.Scheme {
3636
case "memory":
3737
return &factory{
38-
new: func(name string) (cache.Cache, error) {
38+
new: func(name string) (Cache, error) {
3939
return cache.NewMemory(0), nil
4040
},
4141
}, nil
@@ -45,7 +45,7 @@ func NewFactory(config Config) (Factory, error) {
4545
return nil, fmt.Errorf("can't create redis client: %w", err)
4646
}
4747
return &factory{
48-
new: func(name string) (cache.Cache, error) {
48+
new: func(name string) (Cache, error) {
4949
return cache.NewRedis(client, name, 0), nil
5050
},
5151
}, nil
@@ -55,6 +55,6 @@ func NewFactory(config Config) (Factory, error) {
5555
}
5656

5757
// New implements Factory.
58-
func (f *factory) New(name string) (cache.Cache, error) {
58+
func (f *factory) New(name string) (Cache, error) {
5959
return f.new(keyPrefix + name)
6060
}

pkg/cache/memory_bench_test.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ func BenchmarkMemoryCache_ConcurrentReads(b *testing.B) {
179179

180180
for _, bm := range benchmarks {
181181
b.Run(bm.name, func(b *testing.B) {
182+
b.SetParallelism(bm.goroutines)
182183
b.ResetTimer()
183184
b.RunParallel(func(pb *testing.PB) {
184185
for pb.Next() {
@@ -206,6 +207,7 @@ func BenchmarkMemoryCache_ConcurrentWrites(b *testing.B) {
206207

207208
for _, bm := range benchmarks {
208209
b.Run(bm.name, func(b *testing.B) {
210+
b.SetParallelism(bm.goroutines)
209211
b.ResetTimer()
210212
b.RunParallel(func(pb *testing.PB) {
211213
i := 0
@@ -238,6 +240,7 @@ func BenchmarkMemoryCache_MixedWorkload(b *testing.B) {
238240

239241
for _, bm := range benchmarks {
240242
b.Run(bm.name, func(b *testing.B) {
243+
b.SetParallelism(bm.goroutines)
241244
b.ResetTimer()
242245
b.RunParallel(func(pb *testing.PB) {
243246
r := rand.New(rand.NewSource(time.Now().UnixNano()))
@@ -287,6 +290,7 @@ func BenchmarkMemoryCache_Scaling(b *testing.B) {
287290
cache.Set(ctx, key, value)
288291
}
289292

293+
b.SetParallelism(bm.goroutines)
290294
b.ResetTimer()
291295
b.RunParallel(func(pb *testing.PB) {
292296
localI := 0
@@ -355,12 +359,17 @@ func BenchmarkMemoryCache_LargeValues(b *testing.B) {
355359
for i := range value {
356360
value[i] = byte(i % 256)
357361
}
362+
valueStr := string(value)
358363

359364
b.ResetTimer()
360365
b.RunParallel(func(pb *testing.PB) {
361366
for pb.Next() {
362-
cache.Set(ctx, key, string(value))
363-
cache.Get(ctx, key)
367+
if err := cache.Set(ctx, key, valueStr); err != nil {
368+
b.Fatal(err)
369+
}
370+
if _, err := cache.Get(ctx, key); err != nil {
371+
b.Fatal(err)
372+
}
364373
}
365374
})
366375
})
@@ -371,19 +380,20 @@ func BenchmarkMemoryCache_LargeValues(b *testing.B) {
371380
func BenchmarkMemoryCache_MemoryGrowth(b *testing.B) {
372381
cache := cache.NewMemory(0)
373382
ctx := context.Background()
383+
b.ReportAllocs()
374384

375385
sizes := []int{100, 1000, 10000, 100000}
376386

377387
for _, size := range sizes {
378388
b.Run(fmt.Sprintf("%d_items", size), func(b *testing.B) {
379389
b.ResetTimer()
380390

381-
for i := 0; i < b.N; i++ {
391+
for b.Loop() {
382392
// Clear cache
383393
cache.Drain(ctx)
384394

385395
// Add new items
386-
for j := 0; j < size; j++ {
396+
for j := range size {
387397
key := "key-" + strconv.Itoa(j)
388398
value := "value-" + strconv.Itoa(j)
389399
cache.Set(ctx, key, value)

pkg/cache/redis.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ end
2626
hgetallAndDeleteScript = `
2727
local items = redis.call('HGETALL', KEYS[1])
2828
if #items > 0 then
29-
for i = 1, #items, 2 do
30-
redis.call('HDEL', KEYS[1], items[i])
31-
end
29+
local ok = pcall(redis.call, 'UNLINK', KEYS[1])
30+
if not ok then redis.call('DEL', KEYS[1]) end
3231
end
3332
return items
3433
`
@@ -128,14 +127,15 @@ func (r *redisCache) Set(ctx context.Context, key string, value string, opts ...
128127
}
129128
options.apply(opts...)
130129

131-
if err := r.client.HSet(ctx, r.key, key, value).Err(); err != nil {
132-
return fmt.Errorf("can't set cache item: %w", err)
133-
}
134-
135-
if !options.validUntil.IsZero() {
136-
if err := r.client.HExpireAt(ctx, r.key, options.validUntil, key).Err(); err != nil {
137-
return fmt.Errorf("can't set cache item ttl: %w", err)
130+
_, err := r.client.Pipelined(ctx, func(p redis.Pipeliner) error {
131+
p.HSet(ctx, r.key, key, value)
132+
if !options.validUntil.IsZero() {
133+
p.HExpireAt(ctx, r.key, options.validUntil, key)
138134
}
135+
return nil
136+
})
137+
if err != nil {
138+
return fmt.Errorf("can't set cache item: %w", err)
139139
}
140140

141141
return nil

0 commit comments

Comments
 (0)