[PYTHON] Pourquoi ma redis était si lente

Redis est KVS, n'est-ce pas rapide?

Il fut un temps où je le pensais. Si vous n'utilisez pas correctement Redis, les performances chuteront à 1/10 ou moins. Dans cet article, nous avons mesuré les performances de l'implémentation qui démontre les performances de redis et de l'implémentation qui ne le fait pas.

Conclusion

Première conclusion

Les performances d'origine de Redis peuvent être obtenues en utilisant des commandes telles que mget / mset qui lisent et écrivent plusieurs données à la fois. Au contraire, si vous utilisez simplement `` for '' et utilisez une commande telle que get / set pour faire pivoter la boucle une par une, une forte dégradation des performances se produira.

environnement

Mesurez avec python3.

redis était géré par docker.

$ docker run --name redis -d -p 6379:6379 redis:3.2.8
$ redis-cli
127.0.0.1:6379> ping

J'ai installé redis-cli séparément, mais je ne l'utiliserai que pour cette confirmation de communication dans l'article.

mesure

J'écrirai 10000 données et les mesurerai. Dans le but de faire correspondre les conditions, flushdb () est utilisé pour nettoyer et mesurer les redis avant d'écrire des données. De plus, le module timeit de python résume la vitesse d'exécution en une seule fois.

Essayez d'écrire un par un en boucle

$ cat forloop.py 
import timeit
code = '''
import redis
r = redis.StrictRedis()
r.flushdb()
for i in range(10000):
	r.set(i, i)
'''
print(timeit.timeit(code,number=1))
$ python forloop.py 
5.071391730001778

Environ 5 secondes après avoir écrit 10000 fois. C'est 0,5 ms à chaque fois, mais je n'ai pas beaucoup réfléchi à ce stade jusqu'à ce que ce soit lent ...

100 fois pour 100 cas

Afin d'écrire 10000 éléments, je vais le résumer en "100 éléments chaque 100 fois". Dans la commande redis, set devient mset.

$ cat chunk.py 
import timeit
code = '''
import redis
r = redis.StrictRedis()
r.flushdb()
for i in range(100):
    kv = {str(j):j for j in range(i*100,(i+1)*100)}
    r.mset(kv)
'''
print(timeit.timeit(code,number=1))
seiket-mba2011:sandbox seiket$ python chunk.py 
0.2815354660015146

Environ 0,28 seconde pour écrire 10000 enregistrements 0,028 ms par caisse ** 10 fois plus rapide que d'écrire un par un **. Cela fait-il une différence ici? !!

Ecrire 10000 cas en 1 tir

Comme c'est un gros problème, écrivez 10000 éléments à la fois

$ cat all.py 
import timeit
code = '''
import redis
r = redis.StrictRedis()
r.flushdb()
kv = {str(j):j for j in range(10000)}
r.mset(kv)
'''
print(timeit.timeit(code,number=1))
seiket-mba2011:sandbox seiket$ python all.py 
0.22943834099714877

C'est encore plus rapide.

Résumé avec résultats de mesure

La vitesse d'écriture de Redis est extrêmement différente lorsqu'elle est écrite ensemble. Les différences suivantes ont été apportées pour 10000 écritures.

Comment écrire Temps requis pour l'écriture de 10000 enregistrements (sec)
10000 fois une par une 5.071
100 fois pour 100 cas 0.281
10000 caisses chacune 0.229

Comme vous pouvez le voir dans le tableau ci-dessus, l'écriture dans redis dans un lot améliore les performances de ** 10 fois ou plus ** (ou ** l'écriture un par un entraîne une dégradation des performances de 1/10 ou moins ** ) Se produit. Si quoi que ce soit, je pense que la ** dégradation des performances ** est plus appropriée.

Bien que cela ne soit pas mentionné dans l'article, il existe une tendance similaire lors de la lecture, il est donc extrêmement préférable de lire en une seule fois en termes de performances. Surtout lorsque vous utilisez redis pour la vitesse, il est fatalement lent d'accéder un par un.

gist

Le code source utilisé pour la mesure est le même que dans l'article, mais il est également indiqué ci-dessous. https://gist.github.com/seiketkm/3ca7deb28e8b0579a6e443cc7f8f9f65

Recommended Posts

Pourquoi ma redis était si lente
Pourquoi l'importation de django-import-export est si lente et que faire