为什么PHP7在执行这个简单循环时比Python3快得多?

时间:2017-12-30 05:33:18

标签: php python performance

作为一个非常简单的基准测试,我在同一个Raspberry Pi 3模型B上在PHP 7.0.19-1和Python 3.5.3(命令行)上执行了以下简单代码。

与PHP相比,Python的执行时间可怕(74秒对1.4秒)。任何人都可以帮助我理解为什么执行在Python上需要这么长时间?有什么我做错了,或者一些优化/设置可以提高其性能以达到或超过PHP的性能?或者Python的速度要慢得多(当然不是!)?

是的,我看到了this benchmark,它报告了PHP 7超越其他语言,但是你认为在进行这么简单的操作时两者都会得到相当优化。

如果用字符串赋值替换加法,Python执行循环的速度大约快两倍。但这仍然是34秒vs 1.1秒。

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);

结果: 100000的时间是0.036377191543579 1000000的1000000时间为0.18501400947571 100000000的1000000时间是1.3939099311829

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))

结果: 1000000的时间是0.761641 百万 10000000的时间是7.427618000000001 千万 100000000的时间是74.320387 亿

5 个答案:

答案 0 :(得分:9)

当你以相同的周期计数运行它们而不是让Python数量增加一个数量级时,它们彼此之间的数量级都在一个数量级之内:

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))

答案 1 :(得分:1)

在CPython 3中,循环本身的速度似乎慢了两倍:

https://ideone.com/bI6jzD

.fixed-menu {
  position: fixed;
  z-index: 9999999;
  left: 0;
  display: flex;
  width: 40.5px;
  flex-direction: column;
  justify-content: start;
  align-items: center;
}
.submenu {
  height: 40.5px;
  position: relative;
  left: 41px;
  display: flex;
  flex-direction: row;
  max-width: calc(100vw);
}

https://ideone.com/l35EBc

<?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);

但是,这只是Python的标准实现,它更关心易于理解而不是快速。例如,PyPy3.5 v6.0.0在笔记本电脑上以0.06s而不是1.70s的速度运行空循环。

答案 2 :(得分:1)

你们不公平。这两段代码做的不一样。

虽然PHP仅增加两个变量($ a和$ i),但Python在循环之前会生成一个范围。

因此,为了进行公平的比较,您的Python代码应为:

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,速度要快得多:

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

VS

>>> print(test2(100000000))
Time for 100000000 was 3.079545

答案 3 :(得分:0)

正如其他人指出的那样,您的参数对于Python代码而言是一个数量级的偏离。但是我只是想补充一点,无论何时编写任何代码,如Rafael Beckel在其答案中指出的那样,都应尽可能避免在循环条件下使用可调用对象。在每次迭代中都会执行可调用对象,这会导致性能下降,这在OP的基准测试结果中很明显。

虽然这个问题比较古老,但这只是很小的部分,但对于使用任何语言的初学者来说都是有用的信息。

答案 4 :(得分:0)

使用range的PHP代码比没有代码更快。我的版本:

<?php

declare(strict_types=1);

function test(int $x): int
{
    $range = range(1, $x);
    $a = 0;
    $t1 = microtime(true);
    foreach($range as $i)
    {
        $a++;
    }
    $t2 = microtime(true);

    echo 'Time for ' . $x . ' was ' . ($t2 - $t1) . PHP_EOL;

    return $a;
}


echo test(100000000);