A.K. Ngo | Average intelligence, uncommon common sense.

Dec/08

5

PHP Faster than Python?

One of my friends (bwilliam) pointed out to me this webpage "Python vs PHP, Python runs slower?" It intrigued me since I already did something similar to this before here. It has been said that Python is faster than PHP, but why in this case, is Python clearly slower than PHP? I was hoping that the user comments on that page would have an answer, but most people just posted a better implementation of finding prime numbers. So I took a little bit of time out of my hectic schedule to find the cause.

Here are the two scripts written by Teifion in PHP and Python:

PHP:

<?php
$primeNumbers = array();
$output = ;

for ($i = 2; $i < 100000; $i++)
{
        $divisible = false;

        foreach ($primeNumbers as $number)
        {
                if ($i % $number == 0)
                {
                        $divisible = true;
                }
        }

        if ($divisible == false)
        {
                $primeNumbers[] = $i;
                $output .= $i;
        }
}

echo $output;
?>


Python:

primeNumbers = []
output = []

for i in xrange(2, 100000):
        divisible = False

        for number in primeNumbers:
                if i % number == 0:
                        divisible = True

        if divisible == False:
                primeNumbers.append(i)
                output.append(str(i))

print .join(output)

 

I did some benchmark on his code as well and I received similar numbers to his,

Python
real    2m11.903s
user    2m11.456s
sys     0m0.038s

real    2m11.141s
user    2m10.677s
sys     0m0.067s

real    2m11.612s
user    2m10.956s
sys     0m0.050s

PHP
real    1m12.626s
user    1m12.303s
sys     0m0.034s

real    1m16.523s
user    1m15.815s
sys     0m0.040s

real    1m12.982s
user    1m12.686s
sys     0m0.033s

It is clear from these numbers that PHP is faster than Python. It’s around 60 seconds faster, that’s nearly %50! So I looked at the code more carefully and realized that the two scripts weren’t equivalent to each other. To eliminate this difference would lend us a clearer picture of what is going on. Here are the lines of code I will be concentrating on,

PHP:

foreach ($primeNumbers as $number)
{
        if ($i % $number == 0)
        {
                $divisible = true;
        }
}


Python:

for number in primeNumbers:
        if i % number == 0:
                divisible = True

I believe the reason behind this is that this portion of code is not equivalent to one another. The reason is that the Python’s for loop has more use than PHP’s. To clarify, Teifion’s use of Python’s for loop in this case can be used on lists, tuples, dictionaries, strings, enumerate, and who knows what else? That is,

for something in type:

has more than one use. The language itself needs to determine what type it’s working on and proceed from there.  On the other hand, PHP’s foreach is strictly used for arrays only, it has no other purposes.

I don’t know Python’s exact implementation of its for loop, but I can imagine it to be quite a bit more complex compared to PHP’s foreach.  To compare the two would be like comparing peelers to knives. So, to have the two scripts behave more similarly, I changed this portion of code to the following,

PHP:

for ($j = 0; $j < count($primeNumbers); $j++)
{
        $number = $primeNumbers[$j];
        if ($i % $number == 0)
        {
                $divisible = true;
        }
}


Python:

for j in xrange(len(primeNumbers)):
        number = primeNumbers[j]
        if i % number == 0:
                divisible = True

The result? You’ll be pretty surpsied,

Python
real    3m49.961s
user    3m49.618s
sys     0m0.063s

real    3m40.732s
user    3m40.396s
sys     0m0.065s

real    3m40.552s
user    3m40.215s
sys     0m0.060s

PHP
real    3m48.447s
user    3m47.926s
sys     0m0.068s

real    3m48.048s
user    3m47.554s
sys     0m0.073s

real    3m52.343s
user    3m51.764s
sys     0m0.063s 

Nearly identical! What do you think? Please don’t tell me that the script can be optimized, I know. That’s besides the point.

· · · · · · ·

3 comments

  • bwilliam · February 10, 2009 at 1:35 am

    Haha. This is great. AK FTW.

  • Antti Kaihola · February 10, 2009 at 2:57 am

    I tried the following subtle changes to see how they affect the performance:

    import array ; primeNumbers = array(‘L’)
    -> almost twice as slow

    if 0 == i % number:
    -> no change

    if not i % number:
    -> slight speedup

    divisible = [1 for number in primeNumbers if i % number == 0]
    if not divisible:
    -> no change

    divisible = [1 for number in primeNumbers if not i % number]
    if not divisible:
    -> slight speedup

    That’s all I could come up with without significantly changing what the code does.

    Two interesting variations which superficially don’t change the algorithm but actually stop the loop at first match:

    divisible = (1 for number in primeNumbers if i % number == 0)
    try:
    divisible.next()
    except StopIteration:
    primeNumbers.append(i)

    A version using Python 2.5 any():

    for i in xrange(2, 10000):
    divisible = any(i % number == 0 for number in primeNumbers)
    if not divisible:
    primeNumbers.append(i)

    These two of course are in fact changing the algorithm.

    (by the way, you have no help for comment formatting so I don’t know if my code blocks will format correctly)

  • Admin comment by A.K. · February 10, 2009 at 5:59 pm

    Brandon,
    LOL, you are such a prick.

    Antti,
    Those are very interesting observations. I would expect the same results for the same modifications in PHP as well. Sorry about the formatting, I didn’t install a plugin for comment coding.

Leave a Reply

<<

>>