Last active
August 25, 2021 23:40
-
-
Save AhmadElsagheer/6f5c2f65f629a6c667586e2263606ce7 to your computer and use it in GitHub Desktop.
Redis mget vs hget with keys sharing prefix
This file contains hidden or 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
package benchmark | |
// Processor: Intel® Core™ i3-2348M CPU @ 2.30GHz × 4 | |
// Memory: 5.7 GiB | |
// | |
// Benchmarking on 100,000 records | |
// - record key length = 50 | |
// - length of common key (prefix) among all records = 15 | |
// - record value length = 5 | |
// | |
// Results (avg of 10 runs): | |
// # queries | mget | hmget | |
// 1 | 142 ms | 128 ms | |
// 10 | 1395 ms | 1314 ms | |
// 100 | 13739 ms | 13085 ms | |
// 1000 | 137224 ms | 127494 ms | |
import ( | |
"fmt" | |
"math/rand" | |
"strconv" | |
"time" | |
"github.com/go-redis/redis" | |
) | |
var ( | |
queriesCount = []int{1, 10, 100, 1000} | |
runsCount = 100 | |
) | |
const ( | |
redisAddress = "localhost:6379" | |
redisPassword = "" | |
redisDatabase = 0 | |
recordsCount = 100000 | |
commonKeyLength = 15 | |
keyLength = 50 | |
valueLength = 5 | |
) | |
var ( | |
client *redis.Client | |
commonKey string | |
subkeys []string | |
values []string | |
) | |
func setup() { | |
rand.Seed(37) | |
client = redis.NewClient(&redis.Options{ | |
Addr: redisAddress, | |
Password: redisPassword, | |
DB: redisDatabase, | |
}) | |
const letters = "abcdefghijklmnopqrstuvwxyz" | |
randomString := func(length int) string { | |
str := make([]byte, length) | |
for i := range str { | |
str[i] = letters[rand.Intn(len(letters))] | |
} | |
return string(str) | |
} | |
commonKey = randomString(commonKeyLength) | |
subkeys, values = make([]string, recordsCount), make([]string, recordsCount) | |
for i := range subkeys { | |
subkeys[i] = randomString(keyLength - commonKeyLength) | |
values[i] = randomString(valueLength) | |
} | |
} | |
func mgetSetup() []string { | |
pairs := make([]interface{}, len(subkeys)*2) | |
keys := make([]string, len(subkeys)) | |
j := 0 | |
for i := range subkeys { | |
keys[i] = commonKey + subkeys[i] | |
pairs[j] = keys[i] | |
pairs[j+1] = values[i] | |
j += 2 | |
} | |
client.MSet(pairs...) | |
return keys | |
} | |
func hmgetSetup() (string, []string) { | |
pairs := make(map[string]interface{}, len(subkeys)*2) | |
for i := range subkeys { | |
pairs[subkeys[i]] = values[i] | |
} | |
client.HMSet(commonKey, pairs) | |
return commonKey, subkeys | |
} | |
func mget() func() { | |
client.FlushDB() | |
fields := mgetSetup() | |
return func() { | |
client.MGet(fields...) | |
} | |
} | |
func hmget() func() { | |
client.FlushDB() | |
key, fields := hmgetSetup() | |
return func() { | |
client.HMGet(key, fields...) | |
} | |
} | |
func benchmark(name string, fn func() func(), count int) int64 { | |
var totalTime int64 | |
for i := 0; i < runsCount; i++ { | |
runFunc := fn() | |
start := time.Now().UnixNano() | |
for i := 0; i < count; i++ { | |
runFunc() | |
} | |
end := time.Now().UnixNano() | |
totalTime += (end - start) / 1000000 | |
} | |
return totalTime / int64(runsCount) | |
} | |
func Run() { | |
setup() | |
fmt.Printf("%10s | %10s | %10s \n", "# queries", "mget", "hmget") | |
for _, count := range queriesCount { | |
t1 := strconv.FormatInt(benchmark("redis mget", mget, count), 10) | |
t2 := strconv.FormatInt(benchmark("redis hmget", hmget, count), 10) | |
fmt.Printf("%10s | %10s ms | %10s ms \n", strconv.Itoa(count), t1, t2) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
❤️