3

我试图找出最快的方法(在 PHP 5 中)来检查一个值是否是我需要的类型。我创建了两行代码,它们都做同样的事情。问题是我无法根据基准确定哪个最快。

(is_scalar($value) ? intval($value) : 0);
settype($value, 'integer');

我创建了以下测试代码,但除了我自己的 PC(Core2Quad + XP 32bit + php5.2.5)和一个用于测试它的 Dreamhost 帐户外,我没有更多的东西 - 两者都显示此代码的时间大致相同。

$array = array(
    'false' => FALSE,
    'false2'=> 0,
    'false3'=> '0',
    'false4'=> 'FALSE',
    'true'  => TRUE,
    'true2' => 1,
    'true3' => '1',
    'true4' => 'TRUE',

    'char'  => chr(250),
    'char2' => chr(10),
    'utf'   => 0xF0,
    'utf1'  => 0xFE,

    'number' => '452.5435',
    'number2' => '-3948.33e2',
    'number3' => -343.54,
    'number4' => 99.999,
    'number5' => '3jk439fjk23945t324098523.349fj324r',

    'int'   => 2323,
    'int2'  => '2345',
    'int3'  => '0',
    'int4'  => array(),
    'int5'  => '39582347823908270983249078530793249802357846t890234879023490785',
    'int6'  => 3895732890543789324890123467548093248976123890548793289073246789458901234,

    'object3' => new SimpleXMLElement('<xml></xml>'),

    'array' => array(),
    'array2' => array('hello'),
    'array3' => array(3,54,21,0),
    'array4' => array(0.2)
);


$start = microtime(TRUE);

for($x=0;$x<10000;$x++) {
    foreach( $array as $value ) {
        (is_scalar($value) ? intval($value) : 0);
        //settype($value, 'integer');
    }
}

print (microtime(TRUE) - $start). ' seconds';

无论如何,我想知道这里是否还有更多我遗漏的方法,这些方法中的哪一种不仅可以更快地工作,而且还可能产生奇怪的结果。另一件事是,如果这证明整数完全成功 - 那么其他类型(如字符串和浮点数)也应该工作。

:更新:

我刚刚针对 float 类型测试了这些方法,发现 settype() 比 floatval() 慢(0.28 秒)(0.21 秒)。所以这个问题的答案可能只对 int 类型有效。

//Float
(is_scalar($value) ? floatval($value) : 0);
settype($value, 'float');
4

4 回答 4

5

我想您是出于纯粹的理论兴趣而问的,因为在这种特殊情况下的速度差异在实践中并不重要。

让我们看一下php源代码

整数http://lxr.php.net/source/php-src/ext/standard/type.c#142

settype http://lxr.php.net/source/php-src/ext/standard/type.c#95

如您所见,这两个函数都使用相同的 convert_to_long 例程(这反过来又简化为库调用 strtol)。settype 包括将第二个参数与类型字符串进行比较的(很小的)开销,因此它应该稍微慢一些。

最快的方法是使用 (int) cast,因为它不涉及函数调用操作码,而是由 VM 直接执行。

于 2009-10-24T20:14:19.970 回答
1

让我们做一个简单的基准测试:

<?php
$y = "45678912";

$time_start = microtime(true);
for ($i=0; $i<500000; $i++) {
    $x = $y;
    $x = intval($x);
}
echo "\nintval: " . (microtime(true) - $time_start) . " sec.";

$time_start = microtime(true);
for ($i=0; $i<500000; $i++) {
    $x = $y;
    $x = (int)$x;
}
echo "\n(int): " . (microtime(true) - $time_start) . " sec.";

$time_start = microtime(true);
for ($i=0; $i<500000; $i++) {
    $x = $y;
    settype($x, 'int');
}
echo "\nsettype: " . (microtime(true) - $time_start) . " sec.\n";

我在 64 位 Ubuntu 上的结果:

intval: 0.47533583641052 sec.
(int): 0.19618892669678 sec.
settype: 0.51951289176941 sec.

在长整数上,图片是相似的。所以 (int) 是最好的,但没有真正的理由使用 intval() 而不是 settype()

于 2013-08-14T09:22:05.463 回答
0

除非您打算测试无数个值,否则不应该有任何实际的速度差异。任何存在的东西都很小,它不会真正影响任何东西。

于 2009-10-24T19:57:35.167 回答
0

直接(类型)铸造是最快的。这是我现在使用的代码。

(is_scalar($int) && is_numeric($int) ? (int) $int : 0)
于 2009-10-24T21:31:50.870 回答