将 MySQL tinyint 布尔值 (0/1) 转换为 PHP 布尔值 (true/false)
Converting MySQL tinyint booleans (0/1) to PHP booleans (true/false)
我需要反复将 MySQL tinyint(1) 'boolean' 数据类型转换为 PHP 布尔值,我一直在尝试测试最快的方法.我的数据映射如下:
- 空 = 假
- 0 = 假
- 1 = 真
环顾了几个小时后,我似乎找不到任何关于此的性能 explanations/critiques,所以我去尝试自己找到一个可能的解决方案。我的代码如下:
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 秒,以便一目了然地看到缩放比例。从这个测试来看,最好的选择似乎是 !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 的较新版本中可能发生的重大性能变化后,我对它的发展情况很感兴趣,因为现在比赛已经非常接近了!
PHP的默认activity对你来说还不够吗?
无耻地撕掉手册
Converting to boolean
To explicitly convert a value to boolean, use the (bool) or (boolean) casts. However, in most cases the cast is unnecessary, since a value will be automatically converted if an operator, function or control structure requires a boolean argument.
See also Type Juggling.
When converting to boolean, the following values are considered 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
Every other value is considered TRUE (including any resource).
这似乎在以后的版本中得到了优化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
PHP7更厉害:
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
或其他晦涩的结构更能将您的意图传达给其他开发人员)。
首先,您应该在为 $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的不同版本上进行测试
我需要反复将 MySQL tinyint(1) 'boolean' 数据类型转换为 PHP 布尔值,我一直在尝试测试最快的方法.我的数据映射如下:
- 空 = 假
- 0 = 假
- 1 = 真
环顾了几个小时后,我似乎找不到任何关于此的性能 explanations/critiques,所以我去尝试自己找到一个可能的解决方案。我的代码如下:
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 秒,以便一目了然地看到缩放比例。从这个测试来看,最好的选择似乎是 !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 的较新版本中可能发生的重大性能变化后,我对它的发展情况很感兴趣,因为现在比赛已经非常接近了!
PHP的默认activity对你来说还不够吗?
无耻地撕掉手册
Converting to boolean
To explicitly convert a value to boolean, use the (bool) or (boolean) casts. However, in most cases the cast is unnecessary, since a value will be automatically converted if an operator, function or control structure requires a boolean argument.
See also Type Juggling.
When converting to boolean, the following values are considered 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
Every other value is considered TRUE (including any resource).
这似乎在以后的版本中得到了优化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
PHP7更厉害:
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
或其他晦涩的结构更能将您的意图传达给其他开发人员)。
首先,您应该在为 $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的不同版本上进行测试