in_array vs strpos for php中的性能

时间:2014-01-12 02:45:47

标签: php arrays performance strpos

我通过Windows身份验证登录用户,然后将该用户的权限存储在会话变量中。我在数据库中使用分隔的权限存储方法,即:

$rights //retrieved from database 
= 'read,edit,delete,admin'

所以我的问题应该是我;

//generate variable
$_SESSION['userrights'] = $rights ($rights is retrieved from database)

//use strpos to find if right is allowed
if (strpos($_SESSION['userrights'],"admin") !== false) { // do the function }

OR

//make array of rights
$_SESSION['userrights'] = explode(',',$rights)

//use in_array to find if right is allowed
if (in_array("admin",$_SESSION['userrights'])) { // do the function }

OCD问题的一点,因为我认为差异对于我正在做的事情来说几乎可以忽略不计,但这会更快(使用更少的资源)方法?

除了侮辱我的权利存储方法之外,任何答案都会受到赞赏!

4 个答案:

答案 0 :(得分:11)

由于我经常使用大型数据集,我会在关联数组上使用isset!empty并检查密钥,就像@Barmar建议的那样。以下是Intel®Core™i3-540(3.06 GHz)的快速1M基准测试

$test = array("read", "edit", "delete", "admin");

echo "<pre>";

// --- strpos($rights,$test[$i%4]) ---

$rights = 'read,edit,delete,admin';
$mctime = microtime(true);
for($i=0; $i<=1000000; $i++) { if (strpos($rights,$test[$i%4]) !== false) { }}
echo '  strpos(... '.round(microtime(true)-$mctime,3)."s\n";

// --- in_array($test[$i%4],$rights) ---

$rights = array("read", "edit", "delete", "admin");
$mctime = microtime(true);
for($i=0; $i<=1000000; $i++) { if (in_array($test[$i%4],$rights)) { }}
echo 'in_array(... '.round(microtime(true)-$mctime,3)."s\n";

// --- !empty($rights[$test[$i%4]]) ---

$rights = array('read' => 1, 'edit' => 1, 'delete' => 1, 'admin' => 1);
$mctime = microtime(true);
for($i=0; $i<=1000000; $i++) { if (!empty($rights[$test[$i%4]])) { }}
echo '  !empty(... '.round(microtime(true)-$mctime,3)."s\n";

// --- isset($rights[$test[$i%4]]) ---

$rights = array('read' => 1, 'edit' => 1, 'delete' => 1, 'admin' => 1);
$mctime = microtime(true);
for($i=0; $i<=1000000; $i++) { if (isset($rights[$test[$i%4]])) { }}
echo '   isset(... '.round(microtime(true)-$mctime,3)."s\n\n";

echo "</pre>";

获胜者是isset

  strpos(... 0.393s
in_array(... 0.519s
  !empty(... 0.232s
   isset(... 0.209s

答案 1 :(得分:5)

strpos是搜索文本指针的最快方法,php.net网站:

If you only want to determine if a particular needle occurs within haystack, use the     faster and less memory intensive function strpos()....

答案 2 :(得分:1)

证明strpos不是最快的方法,但速度超过in_array的基准:

<?php

echo phpversion() . PHP_EOL;

// build random array
$array = array_fill(0, 10000, 16);
$array = array_map('openssl_random_pseudo_bytes', $array);
$array = array_map('bin2hex', $array);
$array_flipped = array_flip($array);
$string = implode($array);
$random_keys = array_rand($array_flipped, 10);

$loops = 10000;

$start = microtime(true);
for ($i = 0; $i < $loops; $i++) {
    strpos($string, $random_keys[ rand(0, 9) ]);
}
echo __LINE__ . ': ' . round(microtime(true) - $start, 5) . PHP_EOL;

$start = microtime(true);
for ($i = 0; $i < $loops; $i++) {
    in_array($random_keys[ rand(0, 9) ], $array);
}
echo __LINE__ . ': ' . round(microtime(true) - $start, 5) . PHP_EOL;

$start = microtime(true);
for ($i = 0; $i < $loops; $i++) {
    isset($array_flipped[ $random_keys[ rand(0, 9) ] ]);
}
echo __LINE__ . ': ' . round(microtime(true) - $start, 5) . PHP_EOL;

$start = microtime(true);
for ($i = 0; $i < $loops; $i++) {
    $array_flipped = array_flip($array);
    isset($array_flipped[ $random_keys[ rand(0, 9) ] ]);
}
echo __LINE__ . ': ' . round(microtime(true) - $start, 5) . PHP_EOL;

?>

结果:

5.6.31
19: 1.11484
25: 1.3109
31: 0.00237
38: 13.64204

正如您所看到的那样,重要的是不要动态地翻转数组以从isset中受益。

答案 3 :(得分:-1)

如果数据库中存在$_SESSION['userrights'],您是否考虑过对数据库进行查询的可能性?您已经在查询以获取示例中的权限列表,为什么不查询特定的$_SESSION['userrights']并检查是否有任何行返回?