Самое быстрое жонглирование типами PHP с помощью функций settype() против * val()?

StackOverflow https://stackoverflow.com/questions/1618874

  •  06-07-2019
  •  | 
  •  

Вопрос

Я пытаюсь найти самый быстрый способ (в PHP 5) проверить, что значение является тип, который мне нужен это должно быть.Я создал две строки кода, которые обе делают одно и то же.Проблема в том, что я не могу определить, какой из них самый быстрый, основываясь на бенчмарках.

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

Я создал следующий тестовый код, но у меня нет ничего, кроме моего собственного ПК (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';

В любом случае, мне было интересно, может быть, здесь есть что-то еще, чего мне не хватает относительно того, какой из этих методов может не только работать быстрее, но и давать странные результаты.Другое дело, что если это докажет успех в полном объеме с целыми числами, то другие типы, такие как strings и floats, также должны работать.

:ОБНОВЛЕНИЕ:

Я только что протестировал эти методы с типом float и обнаружил, что settype() был медленнее (.28 сек) по сравнению с floatval() (.21 сек).Таким образом, ответ на этот вопрос может быть верен только для типа int.

//Float
(is_scalar($value) ? floatval($value) : 0);
settype($value, 'float');
Это было полезно?

Решение

я предполагаю, что вы спрашиваете из чисто теоретического интереса, потому что различия в скорости в данном конкретном случае не могут считаться важными на практике.

давайте взглянем на исходный код php

внутренний http://lxr.php.net/source/php-src/ext/standard/type.c#142

тип настройки http://lxr.php.net/source/php-src/ext/standard/type.c#95

как вы можете видеть, обе функции используют одну и ту же процедуру convert_to_long (которая, в свою очередь, сводится к библиотечному вызову strtol).settype включает в себя (крошечные) накладные расходы на сравнение второго аргумента со строкой типа, поэтому он должен быть немного медленнее.

самым быстрым методом было бы использовать приведение (int), поскольку оно не включает код операции вызова функции, а выполняется непосредственно виртуальной машиной.

Другие советы

Давайте возьмем простой ориентир:

<?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.

Для длинных целых чисел картина аналогична.So (int) является лучшим, но нет никакой реальной причины использовать intval() вместо settype()

Если вы не планируете тестировать миллион значений, никакой практической разницы в скорости быть не должно.Все, что существует, настолько мало, что на самом деле ни на что не влияет.

Прямое (типовое) литье является самым быстрым.Вот код, который я использую сейчас.

(is_scalar($int) && is_numeric($int) ? (int) $int : 0)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top