First of all, this is a very artificial test. The only building blocks you're measuring here are loops, integer division, array addition, and output.
The two scripts you pasted are not doing the same thing; the PHP one is outputting all numbers at the end (without any separators in between, even), while the python one is outputting one line for each number as it finds it.
Thus if these are the actual scripts, you're not comparing the same code flow.
I changed your scripts to be more similar. I also added a break after the divisor test, showing that a simple algorithmic change makes both scripts an order of magnitude faster (a factor of 10 on my machine).
The new PHP script:
#!/usr/bin/env php
<?php
$primeNumbers = array();
$output = '';
$start = microtime(TRUE);
for ($i = 2; $i < 100000; $i++)
{
$divisible = false;
foreach ($primeNumbers as $number)
{
if ($i % $number == 0)
{
$divisible = true;
break;
}
}
if ($divisible == false)
{
$primeNumbers[] = $i;
$output .= $i;
}
}
echo count($primeNumbers), "\n";
echo "time: ", microtime(TRUE) - $start, "\n";
?>
The new python script:
#!/usr/bin/env python
# -*- Mode: Python -*-
# vi:si:et:sw=4:sts=4:ts=4
import time
start = time.time()
primeNumbers = []
output = ""
for i in xrange(2, 100000):
divisible = False
for number in primeNumbers:
if i % number == 0:
divisible = True
break
if divisible == False:
primeNumbers.append(i)
output += str(i)
print len(primeNumbers)
print 'time: %f' % (time.time() - start)
Here are the runtimes:
- Python, 100000 items, little output, timing inside script: 15.324324, 15.923104, 15.096976
- PHP, 100000 items, little output, timing inside script: 9.3562700748444, 9.6537330150604, 11.526440143585
- Python, same but using xrange: 14.315210, 17.380582, 14.081702 (interestingly enough, seems faster but a wider variation)
Your basic statement, for this contrived case, still seems true - the PHP version is faster. But unless you are writing a prime number generating script, this test will not say much about speed of PHP versus Python.
As an aside - this question shows, more than anything, that it's not the runtime that matters - it's the algorithm. There are much faster algorithms to find all prime numbers up to a given number :)
Here's a faster one in Python, implementing a Sieve of Eratosthenes
#!/usr/bin/env python
# -*- Mode: Python -*-
# vi:si:et:sw=4:sts=4:ts=4
import time
start = time.time()
TOP = 100000
primes = {}
output = ""
for i in range(2, TOP):
primes[i] = True
for i in range(2, TOP):
if primes[i]:
for j in range(i * 2, TOP, i):
primes[j] = False
for i in range(2, TOP):
if primes[i]:
output += str(i)
print 'time: %f' % (time.time() - start)
Runtime for this script: 0.264818
I'd say that's a 60 times improvement on the 10 times improvement I got after adding the break over the original version, but with so small a runtime the margin for error is a bit too big (though it's likely it's actually in favour of the slower tests).
Calculating with an upper limit of 100 times more, this script runs in 30 seconds.
One of the reasons why this script is faster is that it runs in O(n) time, while the original version (with a nested loop) runs in O(n²) time.
The sieve version consumes more memory. For the PHP version to work, I actually had to create a custom .ini to make php use more than 32 MB. Not pasting my PHP version since I'm not really that good a PHP coder and I wouldn't want to skew results with a slow PHP version written by me.