将MySQL tinyint booleans(0/1)转换为PHP布尔值(true / false)

时间:2015-12-30 21:43:42

标签: php mysql performance type-conversion performance-testing

我需要反复将MySQL tinyint(1)'boolean'数据类型转换为PHP布尔值,我一直在尝试测试最快的方法来执行此操作。我的数据映射如下:

  • NULL = FALSE
  • 0 = FALSE
  • 1 = TRUE

环顾四个小时之后,我似乎无法找到任何性能解释/批评,所以我去尝试自己制作一个我找到的可能解决方案。我的代码如下:

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

我选择了850万次迭代,因为我通常希望将最快的测试尽可能接近1秒,以便一目了然地看到缩放。从这个测试来看,似乎最好的选择是空的($ 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的新版本可能会有重大的性能变化之后,我对它的前进方式感兴趣,因为比赛现在非常接近!

3 个答案:

答案 0 :(得分:3)

这似乎已在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或其他模糊构造更好。

答案 1 :(得分:2)

PHP的默认活动是否不够?

从手册

无耻地撕掉
  

转换为布尔值

     

要将值显式转换为boolean,请使用(bool)或(boolean)强制转换。但是,在大多数情况下,转换是不必要的,因为如果运算符,函数或控件结构需要布尔参数,则会自动转换值。

     

另见Type Juggling

     

转换为布尔值时,以下值被视为FALSE:

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
  

其他每个值都被视为TRUE(包括任何资源)。

答案 2 :(得分:1)

首先,您应该在为$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