【问题标题】:Fastest way to convert an int into a binary code string in PHP在 PHP 中将 int 转换为二进制代码字符串的最快方法
【发布时间】:2020-11-17 00:36:03
【问题描述】:

我需要整数(无符号字节)的二进制代码表示。我找到了this solution,在我的情况下是$n = 8

    function _decBinDig($x, $n)
    {
        return substr(decbin(pow(2, $n) + $x), 1);
    }

这令人惊讶地花费了大约 74 毫秒,而我的第一次尝试 - 我认为太慢了:

    function getBinary(int $x)
    {
        return str_pad(base_convert($x, 10, 2), 8, '0', STR_PAD_LEFT);
    }

只需要大约 38 毫秒

有更快的解决方案吗?

【问题讨论】:

  • $st=""; while($n>0){ $st = ($n%2) . $st; $n=intval($n/2); } echo $st; 。不知道你是怎么计时的。你可以试试这个并在这里告诉我。在此先感谢:)
  • $startTime = microtime(true); getBinary(89); $endTime = microtime(true); $elapsed = round(($endTime - $startTime) * 1000000, 2); echo "Execution time : $elapsed ms";
  • 这种方法比getBinary() 慢一些,并且不会产生所需的八个字符
  • 对我来说,所有 3 个解决方案(您的 2 个解决方案和下面答案中的一个)需要 1.4 到 1.6 毫秒来解决。运行每个解决方案 1000 次并重复任务 5 次。我考虑了平均时间、最短时间和最长时间,对于哪个最快,我得到了不同的结果。我认为这个问题太微不足道了,而且这些数字太低而无法在常规环境中进行基准测试,因为结果会受到测试期间在后台运行的其他应用程序导致的 CPU 负载的高度影响。
  • 我的意思是,如果你想优化它,你可能会考虑优化你的硬件而不是软件。

标签: php string binary


【解决方案1】:

对以下五个函数进行了基准测试:

// For a baseline, returns unpadded binary
function decBinPlain(int $x) {
    return decbin($x);
}

// Alas fancier than necessary:
function decBinDig(int $x) {
    return substr(decbin(pow(2, 8) + $x), 1);
}

// OP's initial test
function getBinary(int $x) {
    return str_pad(base_convert($x, 10, 2), 8, '0', STR_PAD_LEFT);
}

// OP's function using decbin()
function getDecBin(int $x) {
    return str_pad(decbin($x), 8, '0', STR_PAD_LEFT);
}

// TimBrownlaw's method
function intToBin(int $x) {
   return sprintf( "%08d", decbin($x));
}

每次迭代 500,000 次,以 10 x (50,000 @ 5) 运行,以下是统计数据:

[average] => [
    [decBinPlain] => 0.0912
    [getDecBin] => 0.1355
    [getBinary] => 0.1444
    [intToBin] => 0.1493
    [decBinDig] => 0.1687
]
[relative] => [
    [decBinPlain] => 100
    [getDecBin] => 148.57
    [getBinary] => 158.33
    [intToBin] => 163.71
    [decBinDig] => 184.98
]
[ops_per_sec] => [
    [decBinPlain] => 548355
    [getDecBin] => 369077
    [getBinary] => 346330
    [intToBin] => 334963
    [decBinDig] => 296443
]

位置一致。 OP 的函数,改为使用decbin 代替base_convert,是返回完整结果的最快函数,但幅度很小。我会选择decbin 只是因为意思很清楚。对于添加左侧填充,str_pad 没有sprintf 复杂。在 W10 和 i5-8250U 上运行 PHP 7.4.4,总运行时间 7.11 秒。

对于基线,调用空的虚拟函数平均需要 0.0542 秒。然后:如果您需要运行足够多的时间来担心每操作分钟的性能提升,将代码内联以避免函数调用会更经济。在这里,函数调用的开销大于上面最慢和最快选项之间的差异!

供日后参考。如果您要对多个选项进行基准测试,我建议您通过单个脚本调用和每个函数的多个连续循环来测试它们。这将有助于消除来自后台程序、CPU 节流(如果使用电池则达到最大功率!!)等的任何“滞后噪音”。然后,调用它几次,看看数字是否稳定。您需要进行超过 1000 次迭代才能获得可靠的数字。尝试例如10K 以上用于更复杂的功能,100K 以上用于更简单的功能。 如果你想证明它,那就烧吧!

【讨论】:

  • Markus AO 首先感谢您深入探讨这个话题。您可能是对的“更经济地将代码内联以避免函数调用”。另一方面:我刚刚被鲍勃叔叔感染,并为我发现了干净的编码。令人着迷的是,仅仅一个视频就足以改变我的编码风格:“......我不应该把这行代码移到它自己的函数中吗?......”
  • @BlackSenator 发现自己在简短地争论“一个函数有多少优点”,甚至快速浏览了我的函数库,看看随着时间的推移我在里面塞进了什么。对我来说,底线似乎是主观的,“如果它合理地放在一行上,如果我可以不假思索地快速输入它,如果它不是在更全球范围内被修改过的东西,那么它不值得一个函数”。现在str_pad(decbin()),如果用例得到修复,我可能不会。但话又说回来,如果有机会我可能想要例如pad 在 16 位之后,一个函数将是有益的。
  • 关于 CPU 经济学。我的开发笔记本电脑为 1M 空白函数调用(循环中)计时 1.1032 秒,其中约 0.1 秒是循环和我的启动内容的开销。如果我运行getDecBin 函数超过 500K 次,则需要 1.38 秒。如果我内联运行 500K 次,则为 0.91 秒。 100K 作为函数:0.32 秒,100K 作为内联:0.19 秒。如果您没有预料到任何接近这种容量的地方,那么担心 CPU 经济性是没有意义的。当“良好的风格”将响应时间增加 0.2+ 秒,或者并发脚本调用使您的服务器陷入困境时,它确实开始成为一个问题。
【解决方案2】:

您可以尝试一种“更好”的方法。

function intToBin(int $x)
{
   return sprintf( "%08d", decbin($x));
}

或者直接调用 sprintf inline。

【讨论】:

  • 感谢您的建议,在大约 10% 的测试用例中,它的性能几乎相同,但不幸的是,在 90% 的情况下,它比 getBinary 慢了大约 50%
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-26
  • 2016-07-13
  • 2013-01-30
  • 2017-03-02
  • 2010-12-13
  • 2020-01-20
  • 2014-11-28
相关资源
最近更新 更多