settype()対* val()関数を使用した最速のPHPタイプジャグリング?
-
06-07-2019 - |
質問
値が必要なタイプ同じことを行う2行のコードを作成しました。問題は、ベンチマークに基づいてどれが最速かを判断できないことです。
(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';
とにかく、これらのメソッドのどれがより速く動作するだけでなく、奇妙な結果をもたらす可能性があるかについて、私が不足しているものがもっとあるかもしれないと思っていました。別のことは、これがintで完全に成功することを証明する必要があるということです-そして、文字列やフロートなどの他の型も動作するはずです。
:UPDATE:
これらのメソッドをfloat型に対してテストしたところ、settype()はfloatval()(.21秒)よりも低速(.28秒)であることがわかりました。したがって、この質問に対する答えは、int型に対してのみ有効です。
//Float
(is_scalar($value) ? floatval($value) : 0);
settype($value, 'float');
解決
この特定の場合の速度の違いは実際には重要であるとは考えられないため、純粋に理論的な関心を求めていると思います。
phpソースコードを見てみましょう
intval 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には、2番目の引数を型文字列と比較するオーバーヘッドが(わずかに)含まれているため、少し遅くなるはずです。
最速の方法は(int)キャストを使用することです。これは、関数呼び出しオペコードを含まないが、VMによって直接実行されるためです。
他のヒント
簡単なベンチマークを見てみましょう:
<?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)が最適ですが、settype()の代わりにintval()を使用する本当の理由はありません
膨大な値のテストを計画している場合を除き、実際の速度の違いはありません。存在するものは非常に小さいため、実際には何も影響しません。
直接(タイプ)キャストが最速です。現在使用しているコードは次のとおりです。
(is_scalar($int) && is_numeric($int) ? (int) $int : 0)