【发布时间】:2015-12-30 21:43:41
【问题描述】:
我需要反复将 MySQL tinyint(1) 'boolean' 数据类型转换为 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
我选择了 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 可能出现的显着性能变化后,我对它的进展很感兴趣,因为现在比赛已经接近尾声了!
【问题讨论】:
-
将
NULL转换为false可能有一天会给您带来严重的麻烦。 “未设置”与“设置为不正确”完全不同。 -
我同意,但客户和团队同意此映射。这是一个超过十年的老系统,其中用户群对数据输入很懒惰,所以他们希望他们看到不经常出现的错误数据 (<.01>耸耸肩
-
$start2未定义 -
@Paolo,感谢您了解这一点,这可能会改变一些事情。让我重新运行并编辑...
标签: php mysql performance type-conversion performance-testing