Pourquoi est-str.traduire beaucoup plus rapide en Python de 3,5 par rapport à Python 3.4?
J'ai essayé de supprimer les caractères d'une chaîne à l'aide de text.translate()
en Python 3.4.
Le code minimal est:
import sys
s = 'abcde12345@#@$#%$'
mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$')
print(s.translate(mapper))
Qu'il fonctionne comme prévu. Cependant, le même programme lors de l'exécution en Python Python 3.4 et 3.5 donne une grande différence.
Le code pour calculer les temps est
python3 -m timeit -s "import sys;s = 'abcde12345@#@$#%$'*1000 ; mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$'); " "s.translate(mapper)"
Le Python 3.4 programme prend 1.3 ms alors que le même programme en Python 3.5 prend seulement 26.4 µs.
Ce qui a amélioré en Python 3.5 qui le rend plus rapide par rapport à Python 3.4?
- Tandis que nous parlons de la performance, ne serait-il pas préférable de générer votre mapper comme ceci:
dict.fromkeys(ord(c) for c in '@#$')
? - J'ai trouvé que cela fait une différence importante. Yep votre chemin, c'est mieux.
- Vouliez-vous dire 50x plus rapide?
- Je n'ai 1300 - 26.4 et ensuite divisé en 1300. J'ai obtenu près de 95%, donc j'ai écrit 🙂 C'est effectivement plus de 50x plus rapide... Mais c'est mon calcul de mal? Je suis peu faible en mathématiques. Je vais apprendre les mathématiques bientôt. 🙂
- vous devriez en faire le tour: 26 / 1300 = 2% de plus pour la version plus rapide ne prend que 2% du temps pris par la version la plus lente => c'est 50x plus rapide.
Vous devez vous connecter pour publier un commentaire.
TL;DR - QUESTION 21118
La longue Histoire
Josh Rosenberg a découvert que le
str.translate()
fonction est très lent par rapport à labytes.translate
, il a soulevé un question, en déclarant que:Pourquoi
str.translate()
lent?La raison principale pour
str.translate()
très lent a été que la recherche dans un dictionnaire Python.L'utilisation de
maketrans
fait de ce problème pour le pire. La même approche à l'aide deoctets
construit un C tableau de 256 éléments de rapide de la table de recherche. Donc l'utilisation de plus haut niveau Pythondict
rend lestr.translate()
en Python 3.4 très lent.Ce qui s'est passé maintenant?
La première approche a été d'ajouter un petit patch, translate_writer, Cependant, l'augmentation de la vitesse n'était pas agréable. Bientôt un autre patch fast_translate a été testé et il a donné de très bons résultats jusqu'à 55% plus rapide.
Le principal changement que peut être vu à partir du fichier, c'est que le Python recherche dans le dictionnaire est changé en un C niveau de la recherche.
Les vitesses de maintenant sont presque les mêmes que
bytes
Une petite note ici, c'est que l'amélioration de la performance est seulement important dans les chaînes ASCII.
Comme J. F. Sebastian mentionne dans un commentaire ci-dessous, Avant de 3.5, traduire l'habitude de travailler de la même façon pour les deux ASCII et non-ASCII cas. Cependant, à partir de 3,5 ASCII cas est beaucoup plus rapide.
Plus tôt ASCII vs non-ascii utilisé pour être presque la même, mais maintenant, nous pouvons voir un grand changement dans la performance.
Il peut être une amélioration de 71.6 µs à 2,33 µs, comme on le voit dans cette réponse.
Le code suivant illustre cette
Dépouillement des résultats:
55
%: comme votre réponse montre, la vitesse peut être1000
s%.python3.5 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
(ascii) vspython3.5 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
(non ascii). Le dernier est beaucoup (10x) plus lent..translate()
c'est à dire, ascii cas est beaucoup plus rapide en Python 3.5 seul (vous n'avez pas besoinbytes.translate()
pour les performances).bytes.translate()
est adapté pour un non-ascii cas, par exemple,'\U0001F602'
est un multi-séquence d'octets (dans la plupart des encodages) et, par conséquent, vous ne pouvez pas la carte à l'aide debytes.translate()
(ce n'est pas la seule raison mais c'est suffisant). Remarque: le premier cas c'est de l'ascii uniquement.