Преобразование логических значений MySQL tinyint (0/1) в логические значения PHP (true / false)

Мне нужно многократно конвертировать MySQL tinyint (1) ‘логический’ тип данных в логическое значение PHP, и я пытался протестировать самый быстрый способ сделать это. Мое сопоставление данных выглядит следующим образом:

  • NULL = FALSE
  • 0 = ЛОЖЬ
  • 1 = ИСТИНА

Посмотрев вокруг в течение нескольких часов, я не могу найти какие-либо объяснения / критические замечания по поводу производительности, поэтому я пошел и попытался найти одно из возможных решений, которые я нашел. Мой код выглядит следующим образом:

echo 'Current PHP Version: ' . phpversion() . '<br /><br />';
$start1 = 1;
$start0 = 0;

$time_start = microtime(TRUE);
for( $i = 0 ; $i < 8500000; $i++ )
{
$answer = !empty($start1);
$answer = !empty($start2);
}
$time_end = microtime(TRUE);
echo 'Did NOT EMPTY in ' . ($time_end - $time_start) . " seconds<br>";

$time_start = microtime(TRUE);
for( $i = 0 ; $i < 8500000; $i++ )
{
$answer = (bool)$start1;
$answer = (bool)$start2;
}
$time_end = microtime(TRUE);
echo 'Did TYPECAST BOOL in ' . ($time_end - $time_start) . " seconds<br>";

$time_start = microtime(TRUE);
for( $i = 0 ; $i < 8500000; $i++ )
{
$answer = $start1 == TRUE;
$answer = $start2 == TRUE;
}
$time_end = microtime(TRUE);
echo 'Did EQUALS TRUE in ' . ($time_end - $time_start) . " seconds<br>";

$time_start = microtime(TRUE);
for( $i = 0 ; $i < 8500000; $i++ )
{
$answer = !!$start1;
$answer = !!$start2;
}
$time_end = microtime(TRUE);
echo 'Did NOT NOT in ' . ($time_end - $time_start) . " seconds<br>";

$time_start = microtime(TRUE);
for( $i = 0 ; $i < 8500000; $i++ )
{
$answer = is_null($start1);
$answer = is_null($start2);
}
$time_end = microtime(TRUE);
echo 'Did IS NULL in ' . ($time_end - $time_start) . " seconds<br>";

Мои результаты следующие:

Current PHP Version: 5.4.16

Did NOT EMPTY in 1.00608086586 seconds
Did TYPECAST BOOL in 2.5599420070648 seconds
Did EQUALS TRUE in 2.7039749622345 seconds
Did NOT NOT in 2.7622299194336 seconds
Did IS NULL in 4.1728219985962 seconds

Я выбрал 8,5 миллионов итераций, так как обычно я хочу, чтобы самый быстрый тест был как можно ближе к 1 секунде, чтобы сразу увидеть масштабирование. Из этого теста кажется, что лучшим выбором является! Empty ($ value) с впечатляюще широким краем.

Я публикую это, чтобы поделиться своими выводами и узнать, знает ли кто-нибудь другой способ получить те же результаты, которые могут быть быстрее, или же это радикально изменится в будущих версиях PHP. В настоящее время мы находимся в среде 5.4, надеясь в следующем году перейти на 5.6, надеясь увидеть php7.

Один из этих методов по-разному побеждает в новых версиях PHP, или есть даже совершенно другой способ, который я пропускаю? Спасибо за ваше понимание!

РЕДАКТИРОВАТЬ:

Как было указано, вышеуказанный тест является неправильным. Правильный тест с дополнительной опцией ниже:

echo 'Current PHP Version: ' . phpversion() . '<br /><br />';

$start1 = 1;
$start0 = 0;

$time_start = microtime(TRUE);
for( $i = 0 ; $i < 14000000; $i++ )
{
$answer = $start1 == 1;
$answer = $start0 == 1;
}
$time_end = microtime(TRUE);
echo 'Did EQUALS 1 in ' . ($time_end - $time_start) . " seconds<br>";

$time_start = microtime(TRUE);
for( $i = 0 ; $i < 14000000; $i++ )
{
$answer = (bool)$start1;
$answer = (bool)$start0;
}
$time_end = microtime(TRUE);
echo 'Did TYPECAST BOOL in ' . ($time_end - $time_start) . " seconds<br>";

$time_start = microtime(TRUE);
for( $i = 0 ; $i < 14000000; $i++ )
{
$answer = $start1 == TRUE;
$answer = $start0 == TRUE;
}
$time_end = microtime(TRUE);
echo 'Did EQUALS TRUE in ' . ($time_end - $time_start) . " seconds<br>";

$time_start = microtime(TRUE);
for( $i = 0 ; $i < 14000000; $i++ )
{
$answer = !!$start1;
$answer = !!$start0;
}
$time_end = microtime(TRUE);
echo 'Did NOT NOT in ' . ($time_end - $time_start) . " seconds<br>";

$time_start = microtime(TRUE);
for( $i = 0 ; $i < 14000000; $i++ )
{
$answer = !empty($start1);
$answer = !empty($start0);
}
$time_end = microtime(TRUE);
echo 'Did NOT EMPTY in ' . ($time_end - $time_start) . " seconds<br>";

$time_start = microtime(TRUE);
for( $i = 0 ; $i < 14000000; $i++ )
{
$answer = !is_null($start1);
$answer = !is_null($start0);
}
$time_end = microtime(TRUE);
echo 'Did NOT IS NULL in ' . ($time_end - $time_start) . " seconds<br>";

Этот тест дает мне:

Current PHP Version: 5.4.16

Did EQUALS 1 in 1.0449228286743 seconds
Did TYPECAST BOOL in 1.0921199321747 seconds
Did EQUALS TRUE in 1.3697588443756 seconds
Did NOT NOT in 1.3729720115662 seconds
Did NOT EMPTY in 1.4694240093231 seconds
Did NOT IS NULL in 3.2058408260345 seconds

Увидев, возможно, существенные изменения производительности в новой версии PHP, я заинтересован в том, как она продвигается вперед, поскольку гонка уже близка!

4

Решение

Сначала вы должны исправить свой тест при назначении значений $start0 а также $start1 но потом вы проверяете $start1 а также $start2 где последний не определен.

После исправления самый быстрый тест — это простое сравнение (вы его не пробовали):

$answer = $start0 == 1

Вот мой код (я запускал его из терминала)

<?php
echo 'Current PHP Version: ' . phpversion() . "\n\n";
$start1 = 1;
$start0 = 0;

$time_start = microtime(TRUE);
for( $i = 0 ; $i < 8500000; $i++ )
{
$answer = $start0 == 1;
$answer = $start1 == 1;
}
$time_end = microtime(TRUE);
echo 'Did COMPARISON in ' . ($time_end - $time_start) . " seconds\n";

$time_start = microtime(TRUE);
for( $i = 0 ; $i < 8500000; $i++ )
{
$answer = !empty($start0);
$answer = !empty($start1);
}
$time_end = microtime(TRUE);
echo 'Did NOT EMPTY in ' . ($time_end - $time_start) . " seconds\n";

/*
.
.
.
*/

Вот результат

Current PHP Version: 5.4.45

Did COMPARISON in 0.60736107826233 seconds
Did NOT EMPTY in 0.75234413146973 seconds
Did TYPECAST BOOL in 0.67925190925598 seconds
Did EQUALS TRUE in 0.80053496360779 seconds
Did NOT NOT in 0.95479583740234 seconds
Did IS NULL in 2.1385459899902 seconds

Вы можете запустить тест на разных версиях PHP здесь

https://3v4l.org/t4K5j

1

Другие решения

Кажется, это было оптимизировано в более поздних версиях PHP:

Current PHP Version: 5.6.16-2+deb.sury.org~wily+1

Did NOT EMPTY in 0.43913006782532 seconds
Did TYPECAST BOOL in 0.40566301345825 seconds
Did EQUALS TRUE in 0.42750406265259 seconds
Did NOT NOT in 0.43936395645142 seconds
Did IS NULL in 1.3173689842224 seconds

PHP 7 еще более впечатляет:

Current PHP Version: 7.0.1-1+deb.sury.org~wily+2

Did NOT EMPTY in 0.21985292434692 seconds
Did TYPECAST BOOL in 0.18928909301758 seconds
Did EQUALS TRUE in 0.17465591430664 seconds
Did NOT NOT in 0.20792722702026 seconds
Did IS NULL in 0.15517687797546 seconds

Типизация в данном случае представляется оптимальным решением как в отношении производительности, так и читабельности (подобная конструкция (bool) $someVar гораздо лучше передает ваше намерение другим разработчикам !!$someVar или другие неясные конструкции).

3

Вам недостаточно активности по умолчанию в PHP?

Бессовестно вырванный из руководства

Преобразование в логическое значение

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

Смотрите также Тип Жонглирование.

При преобразовании в логическое значение следующие значения считаются ЛОЖНЫМИ:

the boolean FALSE itself
the integer 0 (zero)
the float 0.0 (zero)
the empty string, and the string "0"an array with zero elements
an object with zero member variables (PHP 4 only)
the special type NULL (including unset variables)
SimpleXML objects created from empty tags

Любое другое значение считается ИСТИННЫМ (включая любой ресурс).

2
По вопросам рекламы [email protected]