在PHP中,从if语句或数组获取值更快?

在PHP中,从if语句或数组获取值更快?,php,optimization,benchmarking,Php,Optimization,Benchmarking,也许这是个愚蠢的问题,但什么更快 <?php function getCss1 ($id = 0) { if ($id == 1) { return 'red'; } else if ($id == 2) { return 'yellow'; } else if ($id == 3) { return 'green'; } else if ($id == 4) { return 'blue';

也许这是个愚蠢的问题,但什么更快

<?php

function getCss1 ($id = 0) {
    if ($id == 1) {
        return 'red';
    } else if ($id == 2) {
        return 'yellow';
    } else if ($id == 3) {
        return 'green';
    } else if ($id == 4) {
        return 'blue';
    } else if ($id == 5) {
        return 'orange';
    } else {
        return 'grey';
    }
}

function getCss2 ($id = 0) {
    $css[] = 'grey';
    $css[] = 'red';
    $css[] = 'yellow';
    $css[] = 'green';
    $css[] = 'blue';
    $css[] = 'orange';
    return $css[$id];
}

echo getCss1(3);
echo getCss2(3);
?>
我怀疑if语句更快,但我更愿意问

getcss1if语句的速度大约是我的基准测试中getCss2数组访问速度的两倍

microtime的结果:

根据评论,我同意使用翻译数组的可维护性。由于消除了函数开销和数组重新声明,直接访问$css的速度要快得多

getCss1 called 10,000 times in 0.016607999801636 seconds
$css accessed 10,000 times in 0.0026898384094238 seconds
注意:在MacOSX10.8上运行PHP5.3.15。我还改变了调用顺序$id来测试执行路径。

以下是如何计时

将这两个函数保存在一个文件中。定义函数后,先在一个函数上启动计时器,然后在另一个函数上启动计时器。例如:

// Run function 1
$time_start1 = microtime();
getCss1 (2);
$time_end1 = microtime();
$time1 = $time_end1 - $time_start1;

echo "getCss1 function executed in $time1 seconds\n";

// Run function 2
$time_start2 = microtime();
getCss2 (2);
$time_end2 = microtime();
$time2 = $time_end2 - $time_start2;

echo "getCss2 function executed in $time2 seconds\n";

速度应该取决于$id的值,因为如果它是6,它将迭代所有if语句,同时从数组中获取索引值可能会更快。

首先:if/switch语句不是真正动态的,数组是因为它们占用内存。我知道if语句可能会占用内存,但它要小得多

if语句不必在内存中保存变量,因为除了返回值之外,您没有向服务器的ram变量分配任何内容

该数组中的每个项都将首先存储在内存中,然后可以在键值方法中使用


这个规模实在太小了,不重要,但是,我已经用光了大量内存,从数据库创建DynamicKey=>value数组,试图完成各种大型任务。我建议您对这种情况使用switch语句。

您是对的。如果语句更快,因为它会比较最有价值的情况下的所有变体。使用阵列时,需要时间和内存来创建各种情况下的所有变体。 但是
带有数组的变量更具可读性和可用性,如果数组不大且其值为常量,则不是函数的结果!,最好使用数组方式。

第二个函数可能较慢的唯一原因是访问内存所需的时间。 但是,阵列可以存储在处理器的缓存中,这样可以大大缩短时间。 另外,第二个函数在调用堆栈中进行更少的跳转

从理论上讲,这是无法判断的,因为这取决于当前的机器配置和处理器体系结构

如果您进行速度测试,请务必进行多次测试并比较平均速度值…

我将其计时为:

$t = microtime(true);
for($i = 0; $i < 10000000; $i++){
    getCss1(3);
}
echo "getCss1: ".(microtime(true) - $t)."\n";

$t = microtime(true);
for($i = 0; $i < 10000000; $i++){
    getCss2(3);
}
echo "getCss2: ".(microtime(true) - $t)."\n";
使用不同的$id:

$id=6:

getCss1: 4.2732820510864
getCss2: 32.388185024261
getCss3: 20.429337024689
$id=0:

getCss1: 4.3480041027069
getCss2: 14.638042926788
getCss3: 4.2784569263458

因此,if的速度似乎与值的位置无关,而当访问“low”键时,数组访问速度要快得多。

不要忘记getCss13必须始终检查3个条件。getCss3必须获取位置3处数组的值

明确地说:访问阵列更快

这是我的测试应用程序:


您也可以使用switch代替if。Switch比if语句快

switch ($id){
case 1: return "red";
break;
case 2: return "yellow";
break;
case 3: return "green";
...
}

试试看?你知道你可以在php中计时代码执行,对吗?试试看:还有,你忘了在里面加开关盒。为什么不对所有选项进行基准测试呢?这里有一个关于“是否更快”的链接,getCss2将更易于维护。在几纳秒内,它不值得if语句混乱。是否要将其移动到配置文件中?使用较少的测试用例,getCss3实际上要快一点。可能在这么多测试用例中发生了一些内存交换?如果您像这样定义$css=array'grey'、'red'、'yellow'、'green'、'blue'、'orange'这样的$css变量;使用您定义的getCss3运行它,它比getCss1运行得更快;不足为奇。但是我对PHPs的内部结构了解不多。全局是一种糟糕的做法,速度很慢,使用静态变量比if-then-else链更快。。
getCss1: 4.2732820510864
getCss2: 32.388185024261
getCss3: 20.429337024689
getCss1: 4.3480041027069
getCss2: 14.638042926788
getCss3: 4.2784569263458
function getCss1($id = 0) {
  if ($id == 1) {
    return 'red';
  } else if ($id == 2) {
    return 'yellow';
  } else if ($id == 3) {
    return 'green';
  } else if ($id == 4) {
    return 'blue';
  } else if ($id == 5) {
    return 'orange';
  } else {
    return 'grey';
  }
}

function getCss2($id = 0) {
  static $css;
  if ($css === null) {
    $css[] = 'grey';
    $css[] = 'red';
    $css[] = 'yellow';
    $css[] = 'green';
    $css[] = 'blue';
    $css[] = 'orange';
  }
  return $css[$id];
}

$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
  $x = getCss1($i%6);
}
$end = microtime(true);
echo 'getCss1: ' . ($end-$start) . "\n";

$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
  $x = getCss2($i%6);
}
$end = microtime(true);
echo 'getCss2: ' . ($end-$start) . "\n";
switch ($id){
case 1: return "red";
break;
case 2: return "yellow";
break;
case 3: return "green";
...
}