L'autre jour, je faisais un Python benchmarking et je suis tombé sur quelque chose d'intéressant. Voici deux boucles qui font plus ou moins la même chose. La boucle 1 prend environ deux fois plus de temps que la boucle 2 pour s'exécuter .
Boucle 1:
int i = 0
while i < 100000000:
i += 1
Boucle 2:
for n in range(0,100000000):
pass
Pourquoi la première boucle est-elle tellement plus lente? Je sais que c'est un exemple trivial mais cela a piqué mon intérêt. Y a-t-il quelque chose de spécial dans la fonction range () qui la rend plus efficace que l'incrémentation d'une variable de la même manière?
voir le démontage de python octet, vous pouvez avoir une idée plus concrète
utiliser la boucle while:
1 0 LOAD_CONST 0 (0)
3 STORE_NAME 0 (i)
2 6 SETUP_LOOP 28 (to 37)
>> 9 LOAD_NAME 0 (i) # <-
12 LOAD_CONST 1 (100000000) # <-
15 COMPARE_OP 0 (<) # <-
18 JUMP_IF_FALSE 14 (to 35) # <-
21 POP_TOP # <-
3 22 LOAD_NAME 0 (i) # <-
25 LOAD_CONST 2 (1) # <-
28 INPLACE_ADD # <-
29 STORE_NAME 0 (i) # <-
32 JUMP_ABSOLUTE 9 # <-
>> 35 POP_TOP
36 POP_BLOCK
Le corps de boucle a 10 op
gamme d'utilisation:
1 0 SETUP_LOOP 23 (to 26)
3 LOAD_NAME 0 (range)
6 LOAD_CONST 0 (0)
9 LOAD_CONST 1 (100000000)
12 CALL_FUNCTION 2
15 GET_ITER
>> 16 FOR_ITER 6 (to 25) # <-
19 STORE_NAME 1 (n) # <-
2 22 JUMP_ABSOLUTE 16 # <-
>> 25 POP_BLOCK
>> 26 LOAD_CONST 2 (None)
29 RETURN_VALUE
Le corps de boucle a 3 op
Le temps d'exécution du code C est beaucoup plus court que celui de l'interpréteur et peut être ignoré.
range()
est implémentée en C, tandis que i += 1
est interprété.
L'utilisation de xrange()
pourrait rendre la tâche encore plus rapide pour les grands nombres. Commencer par Python 3.0 range()
est le même que précédemment xrange()
.
Il faut dire qu'il y a beaucoup de création et de destruction d'objets en cours avec la boucle while.
i += 1
est le même que:
i = i + 1
Mais parce que Python les entiers sont immuables, il ne modifie pas l'objet existant; il crée plutôt un nouvel objet avec une nouvelle valeur. Il s'agit essentiellement:
i = new int(i + 1) # Using C++ or Java-ish syntax
Le garbage collector aura également une grande quantité de nettoyage à faire. "La création d'objets coûte cher".
Parce que vous utilisez plus souvent du code écrit en C dans l'interpréteur. c'est-à-dire que i + = 1 est en Python, donc lent (comparativement), tandis que la plage (0, ...) est un appel C, la boucle for s'exécutera principalement en C également.
La plupart des appels de méthode intégrés de Python sont exécutés en tant que code C. Le code qui doit être interprété est beaucoup plus lent. En termes d'efficacité mémoire et de vitesse d'exécution, la différence est gigantesque. Les internes python ont été optimisés à l'extrême, et il est préférable de profiter de ces optimisations.