Syl*_*rag 9 php xampp performance
我有一个XAMPP安装,几乎是默认配置.
一般来说,性能并不是什么大问题,因为我主要使用PHP来运行网页和小型网络应用程序.等待几秒钟的页面并不罕见.
但是,我最近从Project Euler中解决了问题,并决定用PHP来完成它们.
尽我所能,我不能让我的代码在不到1分钟的时间内运行(从差不多3分钟开始优化)并且我变得非常尴尬,特别是考虑到Pjt Euler上的大多数海报都报告了1-3秒的时间.(#7,找到第10001个素数)
我将我的代码移植到C#,同一个任务眨眼完成.0.4秒 相同的算法,代码中唯一值得注意的差异是我在C#中使用List来替换我在PHP中使用的数组.
虽然我确实期望C#优于php,但这种差异让我怀疑总体配置问题,但我不知道在哪里看.
造成这种糟糕表现的原因是什么?
编辑:这是代码:
在PHP中:
/*
* Project Euler #7:
* By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
* What is the 10001st prime number?
*/
ini_set('max_execution_time', 300);
echo "start time:" . date("i:s:u") . "<br />";
function isPrime($number, $prevPrimes)
{
foreach ($prevPrimes as $key =>$prime)
{
if ($prime == 1)
{
continue;
}
elseif ($number % $prime == 0)
{
return 0;
}
}
// If we get to here, $number is prime
return $number;
}
$primes = array();
$i = 0;
$nbPrimes = 0;
while ($nbPrimes <10001)
{
$i++;
if ($i % 2 != 0)
{
$result = isPrime($i, $primes);
if ($result != 0)
{
$primes[] = $i;
$nbPrimes++;
}
}
}
echo "#$nbPrimes: $result<br>";
echo "End time:" . date("i:s:u") . "<br />";
Run Code Online (Sandbox Code Playgroud)
在C#中:
public static void RunSnippet()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
List<int> primes = new List<int>();
int i = 0;
int nbPrimes = 0;
int result =0;
while (nbPrimes <10001)
{
i++;
if (i % 2 != 0)
{
result = isPrime(i, primes);
if (result != 0)
{
primes.Add(i);
nbPrimes++;
}
}
}
stopwatch.Stop();
Console.WriteLine("Time elapsed: {0}",
stopwatch.Elapsed);
Console.WriteLine ("#" + nbPrimes + ": " + result.ToString());
}
public static int isPrime(int number, List<int> prevPrimes)
{
foreach (int prime in prevPrimes)
{
if (prime == 1)
{
continue;
}
else if (number % prime == 0)
{
return 0;
}
}
// If we get to here, number is prime
return number;
}
Run Code Online (Sandbox Code Playgroud)
“使用武力 ......”的数学!只是抛出一些毫无意义的代码。以下是可以提高性能的几点。
因此foreach函数无效-循环应在以下时间结束 floor(sqrt(number))
例如:sqrt(64)= 8->所有主除数将是1到8。其他将是它们的乘积(32 = 4 x 8 = 2x2x2x2x2)
使用公式跳到下一个可能的质数
数学:
数字除以2-2,4,6,8,10,12-> 2k + 1 = 2x1 + 1 = 3,5,.....
号码divisable由3 - 3,6,9,12 - >我们已经有6和12,所以3,9,15,21 - > 3(2K-1)= 3(2x1-1)= 3,9,。 ..
isPrime ( number )
{
if ( number == 1 ) return false
elseif ( number < 4 ) return true
elseif ( number % 2 == 0 ) return false
elseif ( number < 9 ) return true
elseif ( number % 3 == 0 ) return false
else
r = floor ( sqrt ( number ) )
f = 5
while ( f <= r )
{
if ( number % f == 0 ) return false
if ( number % ( f + 2 ) == 0 ) return false
f = f + 6
}
return true
}
Run Code Online (Sandbox Code Playgroud)
聚苯乙烯
关于执行速度的差异-PHP是解释语言,要在浏览器中查看结果,您需要运行3个程序-浏览器,服务器,php解释器。您发出一个http请求,服务器调用php(可能还有很多其他东西,例如,日志记录), php读取并执行脚本。比C#中的步骤要多得多。
在C#中,将执行编译后的代码。
最终编辑
以下是 Bakudan 逻辑中的 PHP 代码,它返回以下结果:
start time:44:25:000000
#10001: 104759
End time:44:26:000000
Run Code Online (Sandbox Code Playgroud)
代码:
<?php
echo "start time:" . date("i:s:u") . "\n";
function isPrime($number, &$primes)
{
if ($number === 1) return false;
elseif ($number %2 === 0) return false;
elseif ($number < 4) return true;
elseif ($number < 9) return true;
elseif ($number %3 === 0) return false;
else $r = floor(sqrt($number));
$f = 5;
while ($f <= $r) {
if ($number % $f ===0) return false;
if ($number % ($f+2) === 0) return false;
$f = $f + 6;
}
return true;
}
$primes = array();
$nbPrimes = $i = 0;
while ($nbPrimes < 10001)
{
$i++;
if (isPrime($i, $primes) !== false)
{
$primes[] = $i;
$nbPrimes++;
}
}
echo "#$nbPrimes: " . end($primes) . "\n";
echo "End time:" . date("i:s:u") . "\n";
Run Code Online (Sandbox Code Playgroud)
Bakudan 给了我伪代码,我刚刚为上面的 OP 脚本翻译并编写了它。
编辑2
我稍微清理了代码,没有改进任何东西,可能会增强“可读性”。但是,是的,我认为这是使用 PHP 所能得到的最好的结果,在没有 apache 的 i7 上,它只需要 5 秒。
<?php
echo "start time:" . date("i:s:u") . "\n";
function isPrime($number, &$primes)
{
foreach($primes as $prime) {
if ($number % $prime === 0 && $prime > 1)
return false;
}
}
$primes = array();
$nbPrimes = $i = 1;
while ($nbPrimes <= 10001)
{
if ($i % 2 !== 0 && isPrime($i, $primes) !== false)
{
$primes[] = $i;
$nbPrimes++;
}
$i++;
}
echo "#$nbPrimes: " . end($primes) . "\n";
echo "End time:" . date("i:s:u") . "\n";
Run Code Online (Sandbox Code Playgroud)
编辑
通过将同一个语句中的$prime === 1
to 移到检查之后,又缩短了一秒钟。$number % $prime
if
start time:29:40:000000
#10001: 104743
End time:29:45:000000
Run Code Online (Sandbox Code Playgroud)
采用 Hannes 的建议,严格检查并传递数组作为参考,并添加我自己的一些调整(修改函数内的数组):
ini_set('max_execution_time', 300);
echo "start time:" . date("i:s:u") . "\n";
function isPrime($number, &$prevPrimes)
{
foreach ($prevPrimes as $prime) {
if ($number % $prime === 0 && $prime !== 1)
{
return false;
}
}
// If we get to here, $number is prime
$prevPrimes[] = $number;
return $number;
}
$primes = array();
$i = 0;
$nbPrimes = 0;
while ($nbPrimes < 10001)
{
$i++;
if ($i % 2 !== 0)
{
$result = isPrime($i, $primes);
if ($result !== 0)
{
$nbPrimes++;
}
}
}
echo "#$nbPrimes: $result\n";
echo "End time:" . date("i:s:u") . "\n";
Run Code Online (Sandbox Code Playgroud)
最终结果是:
start time:52:08:000000
#10001: 104743
End time:52:15:000000
Run Code Online (Sandbox Code Playgroud)
VS你的代码:
start time:50:44:000000
#10001: 104743
End time:51:17:000000
Run Code Online (Sandbox Code Playgroud)
这是一个很好的改进,但没有什么能像 C# 那样,只是展示了编译语言的强大功能:)
归档时间: |
|
查看次数: |
1347 次 |
最近记录: |