J'évalue l'expression en 6^6^6
utilisant python
et bc
séparément.
Le contenu du fichier python est print 6**6**6
. Quand j'exécute time python test.py
, j'obtiens la sortie
real 0m0.067s
user 0m0.050s
sys 0m0.011s
Et puis, j'ai exécuté la commande time echo 6^6^6 | bc
qui m'a donné la sortie suivante
real 0m0.205s
user 0m0.197s
sys 0m0.005s
D'après ces résultats, il est clair que le temps sys pris par python et bc était de 11 ms et 5 ms respectivement. La commande bc a surpassé python au niveau du temps sys, mais en ce qui concerne l' utilisateur et le temps réel, python était presque 4 fois plus rapide que bc . Qu'est-ce qui aurait pu y aller. Je n'ai accordé aucune priorité aux processus en tant que tels. J'essaie de comprendre cette situation.
python
performance
process-management
bc
ganessh
la source
la source
echo | bc
implique le lancement d'un sous-shell à cause du tube - c'est de là que vient probablement une partie de votre temps utilisateur supplémentaire. Pour en faire un test équitable, le script python doit lire à partir de stdin pour que vous puissieztime echo 6**6**6 | whatever.py
.echo 6^6^6 | time bc
.6**6**6
expression est réellement calculée au moment de la compilation . Cependant, puisque vous lancez le fichier directement au lieu de l'importer à partir d'un module, cela ne devrait pas avoir d'importance. Pour voir la différence insérée10**12345678
dans una.py
fichier et essayer de l'importer depuis l'interpréteur interactif. Fermez ensuite l'interpréteur, redémarrez-le et importez àa
nouveau. La première fois, cela devrait prendre un temps considérable (car python compile le module), tandis que la deuxième fois qu'il charge le.pyc
, qui devrait être instantané,Réponses:
Python importe un grand nombre de fichiers au démarrage:
Chacun d'eux nécessite un nombre encore plus élevé de tentatives d'ouverture d'un fichier Python, car il existe de nombreuses façons de définir un module:
Chaque "essai", à l'exception de ceux qui sont intégrés, nécessite un appel au niveau du système d'exploitation / système, et chaque "importation" semble déclencher environ 8 messages "d'essai". (Il y avait des moyens de réduire cela en utilisant zipimport, et chaque chemin dans votre PYTHONPATH peut nécessiter un autre appel.)
Cela signifie qu'il y a près de 200 appels système stat avant le démarrage de Python sur ma machine, et "time" affecte cela à "sys" plutôt qu'à "user", car le programme utilisateur attend que le système fasse des choses.
En comparaison, et comme l'a dit terdon, "bc" n'a pas un coût de démarrage aussi élevé. En regardant la sortie de dtruss (j'ai un Mac; "strace" pour un système d'exploitation basé sur Linux), je vois que bc ne fait aucun appel système open () ou stat (), sauf pour charger quelques partagés les bibliothèques sont le début, ce que Python fait bien sûr aussi. De plus, Python a plus de fichiers à lire avant d'être prêt à traiter quoi que ce soit.
L'attente du disque est lente.
Vous pouvez avoir une idée du coût de démarrage de Python en faisant:
C'est 0,032s sur ma machine, tandis que 'print 6 ** 6 ** 6' est 0,072s, donc le coût de démarrage est 1 / 2ème du temps global et le calcul + conversion en décimal est l'autre moitié. Tandis que:
prend 0,005s, et "6 ^ 6 ^ 6" prend 0,184s donc l'exponentiation de bc est plus de 4x plus lente que celle de Python même si c'est 7x plus rapide pour commencer.
la source
J'ai trouvé une bonne réponse sur SO expliquant les différents domaines:
Ainsi, dans votre exemple spécifique, la version python est plus rapide en termes de temps réel nécessaire pour terminer. Cependant, l'approche python passe plus de temps dans l'espace noyau, faisant des appels aux fonctions du noyau. La
bc
commande ne passe pratiquement pas de temps dans l'espace du noyau et tout son temps est passé dans l'espace utilisateur, probablement en exécutant dubc
code interne .Cela ne fait aucune différence pour vous, la seule information qui vous intéresse vraiment
real
est le temps réel écoulé entre le lancement de la commande et l'obtention de sa sortie.Vous devez également savoir que ces minuscules différences ne sont pas stables, elles dépendront également de la charge de votre système et changeront chaque fois que vous exécuterez la commande:
la source
Je vais l'expliquer sous un autre angle.
Pour être honnête,
bc
a l'avantage car il n'a rien à lire sur le disque et n'a besoin que de ses blob / binaires tandis que python doit importer une série de modules + lire un fichier. Votre test pourrait donc être biaisébc
. Pour le tester, vous devez utiliserbc -q file
oùfile
contient:Changer juste cela a modifié le temps d'utilisation
echo
:Pour utiliser le fichier:
(vous devrez utiliser la méthode de terdon pour remarquer de plus grandes différences, mais au moins nous savons qu'elles le sont)
Maintenant, du point de vue de python, python doit lire à partir du disque, compiler et exécuter à chaque fois le fichier, plus charger les modules en tant que points Andrew , ce qui rend le temps d'exécution plus lent. Si vous compilez le code octet du script python, vous remarquerez qu'il faut 50% moins de temps total pour exécuter le code:
compilé:
Comme vous pouvez le voir, plusieurs facteurs peuvent affecter l'exécution du temps entre différents outils.
la source
J'ai eu l'avantage de lire les autres réponses. Pour commencer, les gens comme moi devraient savoir pourquoi nous avons affaire à un entier aussi énorme ici, c'est que les deux
Python
etbc
font une expansion d'exponentiation associative correcte , ce qui signifie que ce n'est pas6^36
nous évaluons mais plutôt6^46656
qui est considérablement plus grand. 1En utilisant des variations sur les commandes suivantes, nous pouvons extraire une moyenne pour un élément spécifique de la sortie du
time
mot réservé et de la commande:Il est possible de suivre une autre voie et de supprimer entièrement le fichier de la comparaison. En outre, nous pouvons comparer le timing de bc avec quelque chose comme la
dc
commande, car historiquement le premier est un "processeur frontal" au second. Les commandes suivantes ont été chronométrées:Notez que la
dc
commande est associative à gauche pour l'exponentiation. 2Nous avons quelques résultats avec
time
(bash) pour 1000 itérations (en secondes):bc
etdc
offrent des performances comparables dans ce contexte.3 résultats moins précis de la commande
/usr/bin/time
GNUtime
(la précision de l'échelle n'est pas valide ici mais les résultats sont similaires):Un avantage
/usr/bin/time
est qu'il offre l'-v
option qui fournit beaucoup plus d'informations qui pourraient éventuellement être utiles.Il est également possible d'évaluer cela en interne pour ainsi dire avec le
timeit
module Python:C'est un peu plus rapide que ce que nous avons vu auparavant. Essayons l'interprète lui-même:
C'est le plus rapide que j'ai vu.
Si nous évaluons une exponentiation moindre comme
6^6
, alors la commande time donne des résultats surprenants - en utilisant les mêmesfor
commandes de boucle que nous avons utilisées, nous avons maintenant:Donc, avec un entier plus petit
bc
est tout d'un coup beaucoup plus rapide ?? Du redémarrage du système à la deuxième exécution, cela ne fait aucune différence. Pourtant, en même temps, si nous utilisonstimeit
pour Python, nous obtenons:Ce sont des microsecondes , pas des millisecondes, donc cela ne correspond pas aux résultats beaucoup plus lents utilisant la
for
boucle. Peut-être que d'autres outils sont nécessaires pour tester cela plus loin et comme d'autres l'ont expliqué, il y a plus que ce qui semble évident ici. Il semble que Python ait été plus rapide dans le scénario de la question, mais il n'est pas clair si des conclusions peuvent être tirées au-delà de cela ...1. Inutile de dire que cela dépasse la portée de quelque chose comme l'expansion arithmétique de l'écho, c'est
echo $((6**6**6))
-à- direbash
qu'il se trouve également être associatif à droite pour cela, c'est-à-dire6^6^6 = 6^(6^6)
.2. Comparer avec ceci:
6 6 ^ 6 ^ p
.3. Il est possible que la commande GNU time fournisse plus d'informations lorsqu'elle est exécutée sur BSD UNIX (GNU time info document): la plupart des informations affichées par 'time' sont dérivées de l'appel système 'wait3'. Les nombres sont aussi bons que ceux retournés par 'wait3'. De nombreux systèmes ne mesurent pas toutes les ressources dont le «temps» peut rendre compte; ces ressources sont déclarées nulles. Les systèmes qui mesurent la plupart ou la totalité des ressources sont basés sur 4.2 ou 4.3BSD. Les versions ultérieures de BSD utilisent un code de gestion de mémoire différent qui mesure moins de ressources. - Sur les systèmes qui n'ont pas d'appel «wait3» qui renvoie des informations d'état, l'appel système «times» est utilisé à la place. Il fournit beaucoup moins d'informations que 'wait3', donc le temps de ces systèmes signale la plupart des ressources comme nulles.
la source