web-dev-qa-db-fra.com

Pourquoi PHP7 est-il tellement plus rapide que Python3 à exécuter cette boucle simple?

En tant que référence extrêmement simple, j'ai exécuté le code simple ci-dessous sous PHP 7.0.19-1 et Python 3.5.3 (ligne de commande) sur le même modèle B de Raspberry Pi 3.

Le temps d'exécution de Python était de horrible par rapport à celui de PHP (74 secondes contre 1,4 seconde). Quelqu'un peut-il m'aider à comprendre pourquoi l'exécution prend beaucoup plus de temps sur Python? Y a-t-il quelque chose que je fais de mal, ou des optimisations/paramètres qui amélioreraient ses performances pour atteindre ou dépasser celles de PHP? Ou est-ce que Python est beaucoup plus lent (sûrement pas!)?

Oui, j’ai vu ce repère , qui rapporte PHP 7 au-delà des autres langues, mais on pourrait penser que les deux seraient optimisés de manière tout aussi uniforme lors d’une opération aussi simple.

Python exécute la boucle environ deux fois plus vite si une attribution de chaîne est substituée à l'addition. Mais cela reste 34 secondes contre environ 1,1 seconde.

Code PHP7:

<?php

function test($x)
{
    $t1 = microtime(true);
    $a = 0;
    for($i = 0; $i < $x; $i++)
    {
        $a++;
    }
    $t2 = microtime(true);

    echo "Time for $x was " . ($t2 - $t1) . "\n";

    return $a;
}


echo test(100000);
echo test(1000000);
echo test(10000000);

Résultats: Le temps pour 100 000 était de 0,036377191543579 100000Le temps pour 1000000 était de 0,18501400947571 1000000 Le temps pour 10000000 était de 1,3939099311829.

Code Python3:

import time
def test(x):
    t1 = time.clock()
    a = 0
    for i in range(x):
        a += 1
    t2 = time.clock()
    print("Time for {} was {}".format(x, t2 - t1))
    return x

print(test(1000000))
print(test(10000000))
print(test(100000000))

Résultats: Le temps pour 1000000 était de 0,761641 1000000 Le temps pour 10 000 000 était de 7,427618000000001 10000000 Le temps pour 100000000 était de 74,320387 100000000.

7
Ryan Griggs

Ils se situent tous deux dans un ordre de grandeur l'un de l'autre, lorsque vous les exécutez avec un nombre de cycles identique plutôt que d'avoir un nombre de pythons plus grand d'un ordre de grandeur:

PHP: https://ideone.com/3ebkai 2.7089s

<?php

function test($x)
{
    $t1 = microtime(true);
    $a = 0;
    for($i = 0; $i < $x; $i++)
    {
        $a++;
    }
    $t2 = microtime(true);

    echo "Time for $x was " . ($t2 - $t1) . "\n";

    return $a;
}


echo test(100000000);

Python: https://ideone.com/pRFVfk 4.5708s

import time
def test(x):
    t1 = time.clock()
    a = 0
    for i in range(x):
        a += 1
    t2 = time.clock()
    print("Time for {} was {}".format(x, t2 - t1))
    return x

print(test(100000000))
8
Amber

La boucle elle-même semble être deux fois plus lente dans CPython 3:

https://ideone.com/bI6jzD

<?php
function test($x)
{
    $t1 = microtime(true);
    $a = 0;
    for($i = 0; $i < $x; ++$i)
    {
        //1.40s Reassign and use $a.
        //$a += 1;
        //1.15s Use and increment $a.
        //$a++;
        //0.88s Increment and use $a.
        //++$a;
        //0.69s Do nothing.
    }
    $t2 = microtime(true);
    echo "Time for $x was " . ($t2 - $t1) . "\n";
    return $a;
}
echo test(1e8);

https://ideone.com/l35EBc

import time

def test(x):
    t1 = time.clock()
    #>5s
    #from functools import reduce
    #a = reduce(lambda a, i: a + i, (1 for i in range(x)), 0)
    a = 0
    for i in range(x):
        #4.38s
        #a += 1
        #1.89s
        pass
    t2 = time.clock()
    print("Time for {} was {}".format(x, t2 - t1))
    return x

print(test(int(1e8)))

Cependant, ce n’est que l’implémentation standard de Python qui se soucie plus de la facilité de compréhension que de la rapidité. PyPy3.5 v6.0.0 par exemple, exécute cette boucle vide en 0.06s au lieu de 1.70s sur mon portable.

1
Cees Timmerman

Vous n'êtes pas juste les gars. Les deux morceaux de code ne font pas la même chose.

Alors que PHP n'incrémente que deux variables ($ a et $ i), Python génère une plage avant sa boucle.

Donc, pour avoir une comparaison juste, votre code Python devrait être:

import time
def test2(x):
    r = range(x) #please generate this first
    a = 0

    #now you count only the loop time
    t1 = time.clock()
    for i in r:
        a += 1
    t2 = time.clock()

    print("Time for {} was {}".format(x, t2 - t1))
    return a

Aaaaaaand, c'est BEAUCOUP plus rapide:

>>> print(test(100000000))
Time for 100000000 was 6.214772

CONTRE

>>> print(test2(100000000))
Time for 100000000 was 3.079545
1
Rafael Beckel