La bibliothèque standard standard pour la gestion du temps en Python est datetime
.
C'est une bibliothèque qui peut être utilisée sans aucun problème même si vous l'utilisez correctement, et vous n'avez même pas à vous soucier des performances si vous l'appelez un peu.
Cependant, lorsqu'il est nécessaire de générer une date-heure des dizaines de milliers ou des dizaines de millions de fois, le goulot d'étranglement devient apparent.
Donc, j'ai trouvé que les performances peuvent être améliorées un peu en faisant attention à un petit détail, alors je voudrais vous le présenter.
La conclusion est que nous utiliserons la bibliothèque standard timezone
pour générer datetime
.
Tout à coup, écrivez seulement la conclusion. Après cela, veuillez voir si vous êtes intéressé. Je pense qu'il est préférable de générer datetime comme suit. Le point est de savoir s'il faut spécifier «timezone». .. .. C'est tout.
from datetime import datetime, timedelta, timezone
#Génération de fuseau horaire
JST = timezone(timedelta(hours=+9), 'JST')
# GOOD,Le fuseau horaire est spécifié. de bonne heure
datetime.now(JST)
datetime.fromtimestamp(Heure UNIX, JST)
# NG,Il utilise un temps dépendant de l'environnement. Lent par rapport à ne pas spécifier de fuseau horaire
datetime.now()
datetime.fromtimestamp(Heure UNIX)
Immédiatement, je vais essayer de générer «datetime» par diverses méthodes. Mesurez le temps de traitement lorsque «datetime» est généré 10 millions de fois. Dans quelle mesure les performances changent selon que le fuseau horaire est spécifié ou non. J'espère que vous pourrez vous y référer.
C'est le modèle le plus rapide (pour autant que je sache).
zikan1.py
from datetime import datetime, timedelta, timezone
JST = timezone(timedelta(hours=+9), 'JST')
for _ in range(10000000):
datetime.now(JST)
$ time python zikan1.py
real 0m7.581s
user 0m7.167s
sys 0m0.114s
Il boucle 10 millions de fois et le résultat est de 7 secondes.
Si vous ne spécifiez pas le fuseau horaire, il sera légèrement plus lent. Légèrement. ..
zikan2.py
from datetime import datetime
for _ in range(10000000):
datetime.now()
$ time python zikan2.py
real 0m9.609s
user 0m9.149s
sys 0m0.111s
C'est environ 9 secondes. C'est un peu tard.
pytz est une bibliothèque souvent utilisée pour spécifier le fuseau horaire dans les séries Python2. C'est parce que Python2 n'a pas encore implémenté la classe timezone. .. ..
zikan3.py
import pytz
from datetime import datetime
# third party
JST = pytz.timezone('Asia/Tokyo')
# performance testing
for _ in range(10000000):
datetime.now(JST)
$ time python zikan3.py
real 1m9.173s
user 1m6.999s
sys 0m0.584s
C'était beaucoup plus lent que prévu. Nous en discuterons plus tard.
Comme c'est une bonne idée, j'ai également essayé l'analyse comparative avec le système Python 2.
Pour la série Python2, seule la classe d'interface pour le fuseau horaire appelée tzinfo
est fournie, vous devez donc l'implémenter vous-même. Fastidieux. Le «pytz» est peut-être devenu populaire à cause du problème.
zikan4.py
from datetime import datetime, timedelta, tzinfo
class JST(tzinfo):
def utcoffset(self, dt):
return timedelta(hours=9)
def dst(self, dt):
return timedelta(0)
def tzname(self, dt):
return 'JST'
for _ in range(10000000):
datetime.now(JST())
$ time python zikan3.py
real 0m55.416s
user 0m51.131s
sys 0m1.532s
lent. .. .. ..
Fuseau horaire spécifié (7s) <Fuseau horaire non spécifié (9s) <python2 (51s) <pytz (66s) C'est devenu un sentiment.
La classe de fuseau horaire de la bibliothèque standard et la classe de fuseau horaire de pytz
sont des classes d'implémentation de tzinfo
. Cependant, il y a une différence entre le ciel et la terre en termes de performances.
Pourquoi?
Je n'ai pas trouvé de réponse définitive, mais quand je la profile, la différence entre les deux est évidente.
$ python -m cProfile -s cumtime zikan1.py
10001072 function calls (10001061 primitive calls) in 9.107 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
2/1 0.000 0.000 9.107 9.107 {built-in method builtins.exec}
1 3.149 3.149 9.107 9.107 zikan1.py:1(<module>)
10000000 5.950 0.000 5.950 0.000 {built-in method now}
3/1 0.000 0.000 0.009 0.009 <frozen importlib._bootstrap>:958(_find_and_load)
3/1 0.000 0.000 0.009 0.009 <frozen importlib._bootstrap>:931(_find_and_load_unlocked)
$ python -m cProfile -s cumtime zikan3.py
70022021 function calls (70021903 primitive calls) in 83.138 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
14/1 0.001 0.000 83.138 83.138 {built-in method builtins.exec}
1 3.185 3.185 83.138 83.138 zikan5.py:1(<module>)
10000000 9.225 0.000 79.868 0.000 {built-in method now}
10000000 17.973 0.000 70.643 0.000 tzinfo.py:179(fromutc)
20000000 43.347 0.000 43.347 0.000 {method 'replace' of 'datetime.datetime' objects}
La partie à laquelle je veux faire attention est lors de l'exécution de zikan3.py
10000000 17.973 0.000 70.643 0.000 tzinfo.py:179(fromutc)
20000000 43.347 0.000 43.347 0.000 {method 'replace' of 'datetime.datetime' objects}
C'est la partie de.
pytz a été appelé datetime.replace ()
et a été exécuté 20 millions de fois. Non seulement cela, la fonction fromutc
est appelée.
En d'autres termes, le processus tz.fromutc (datetime.now (). Replace (tzinfo = tz))
est en cours d'exécution.
Générer la date / heure de l'heure en UTC => Générer la date et l'heure avec le fuseau horaire => Convertir en date / heure du fuseau horaire. .. C'est vrai.
D'un autre côté, quand le fuseau horaire de la bibliothèque standard est donné comme argument, il semble que «{méthode intégrée maintenant}» traite ce côté, et bien que les spécifications internes soient inconnues, il semble traiter efficacement. Je peux te dire ça.
Au fait ... En d'autres termes, utilisons le fuseau horaire standard de la bibliothèque! c'est tout!
N'hésitez pas à signaler toute inexactitude telle que des erreurs typographiques.
Recommended Posts