如何加速PHP数学


How to speed up PHP math?

我试图从这里对短代码进行基准测试,将其直接从javascript转换为PHP

Javascript:

(function() {
    var a = 3.1415926, b = 2.718;
    var i, j, d1, d2;
    for(j=0; j<10; j++) {
        for(i=0; i<100000000; i++) {
            a = a + b;
        }
    }
    console.log("a = " + a);
})();

.PHP:

<?php
$a = 3.1415926;
$b = 2.718;
for($j=0; $j<10; $j++) {
    for($i=0; $i<100000000; $i++) {
        $a = $a + $b;
    }
}
echo "a = $a'n";

在控制台上运行两者(我的Macbook终端,节点v5.7.0与PHP 7.0.4(,结果非常令人费解:

$ time node test.js
a = 2717999973.76071
real    0m1.340s
user    0m0.912s
sys 0m0.021s
$ time php t.php
a = 2717999973.7607
real    2m40.239s
user    2m35.271s
sys 0m0.507s

基本数学运算中的 PHP 真的比节点慢 120 倍吗?有什么可以优化的吗?

虽然我无法解释javascript和PHP之间的巨大差异,但我已经能够在一个小的更改中使PHP代码的处理速度提高约30%。

在本地运行了一些测试后,我改变了

$a = $a + $b;

$a += $b;

运行时间为 53-55 秒,低于 78-80(在我的机器上 - i5 8GB RAM 和慢速磁盘(。 使用类似的节省估计值(四舍五入为 25%(应该总共需要大约 2 分钟的处理时间。 显然,这并不接近 JavaScript 时代。

根据您实际想要运行的内容(因为基准测试只能告诉您这么多(,您可以进行其他改进,但并不总是针对如此大的数字。

JavaScript 的编译比例接近 1:1,因此 10^9 个循环中没有太多的肉体,运行速度与 CPU 允许的速度一样快(这里:2.14 秒,使用旧节点,版本 v0.10.25(。

另一边的PHP做了很多事情,尤其是Zend机器。如果你用VLD转储你的小程序的操作码,你会得到(php 7.0.5(:

$ php -d vld.active=1 -d vld.execute=0   -f benchmark.php
Finding entry points
Branch analysis from position: 0
Jump found. Position 1 = 14
Branch analysis from position: 14
Jump found. Position 1 = 16, Position 2 = 4
Branch analysis from position: 16
Jump found. Position 1 = -2
Branch analysis from position: 4
Jump found. Position 1 = 10
Branch analysis from position: 10
Jump found. Position 1 = 12, Position 2 = 6
Branch analysis from position: 12
Jump found. Position 1 = 16, Position 2 = 4
Branch analysis from position: 16
Branch analysis from position: 4
Branch analysis from position: 6
Jump found. Position 1 = 12, Position 2 = 6
Branch analysis from position: 12
Branch analysis from position: 6
filename:       benchmark.php
function name:  (null)
number of ops:  21
compiled vars:  !0 = $a, !1 = $b, !2 = $j, !3 = $i
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   2     0  E >   ASSIGN                                                   !0, 3.14159
   3     1        ASSIGN                                                   !1, 2.718
   5     2        ASSIGN                                                   !2, 0
         3      > JMP                                                      ->14
   6     4    >   ASSIGN                                                   !3, 0
         5      > JMP                                                      ->10
   7     6    >   ADD                                              ~8      !0, !1
         7        ASSIGN                                                   !0, ~8
   6     8        POST_INC                                         ~10     !3
         9        FREE                                                     ~10
        10    >   IS_SMALLER                                       ~11     !3, 100000000
        11      > JMPNZ                                                    ~11, ->6
   5    12    >   POST_INC                                         ~12     !2
        13        FREE                                                     ~12
        14    >   IS_SMALLER                                       ~13     !2, 10
        15      > JMPNZ                                                    ~13, ->4
  10    16    >   ROPE_INIT                                     3  ~15     'a+%3D+'
        17        ROPE_ADD                                      1  ~15     ~15, !0
        18        ROPE_END                                      2  ~14     ~15, '%0A'
        19        ECHO                                                     ~14
        20      > RETURN                                                   1
branch: #  0; line:     2-    5; sop:     0; eop:     3; out1:  14
branch: #  4; line:     6-    6; sop:     4; eop:     5; out1:  10
branch: #  6; line:     7-    6; sop:     6; eop:     9; out1:  10
branch: # 10; line:     6-    6; sop:    10; eop:    11; out1:  12; out2:   6
branch: # 12; line:     5-    5; sop:    12; eop:    13; out1:  14
branch: # 14; line:     5-    5; sop:    14; eop:    15; out1:  16; out2:   4
branch: # 16; line:    10-   10; sop:    16; eop:    20; out1:  -2
path #1: 0, 14, 16, 
path #2: 0, 14, 4, 10, 12, 14, 16, 
path #3: 0, 14, 4, 10, 6, 10, 12, 14, 16, 

两个版本之间的区别是

1,10c1,10
< branch: #  0; line:     2-    5; sop:     0; eop:     3; out1:  14
< branch: #  4; line:     6-    6; sop:     4; eop:     5; out1:  10
< branch: #  6; line:     7-    6; sop:     6; eop:     9; out1:  10
< branch: # 10; line:     6-    6; sop:    10; eop:    11; out1:  12; out2:   6
< branch: # 12; line:     5-    5; sop:    12; eop:    13; out1:  14
< branch: # 14; line:     5-    5; sop:    14; eop:    15; out1:  16; out2:   4
< branch: # 16; line:    10-   10; sop:    16; eop:    20; out1:  -2
< path #1: 0, 14, 16, 
< path #2: 0, 14, 4, 10, 12, 14, 16, 
< path #3: 0, 14, 4, 10, 6, 10, 12, 14, 16, 
---
> branch: #  0; line:     2-    5; sop:     0; eop:     3; out1:  13
> branch: #  4; line:     6-    6; sop:     4; eop:     5; out1:   9
> branch: #  6; line:     7-    6; sop:     6; eop:     8; out1:   9
> branch: #  9; line:     6-    6; sop:     9; eop:    10; out1:  11; out2:   6
> branch: # 11; line:     5-    5; sop:    11; eop:    12; out1:  13
> branch: # 13; line:     5-    5; sop:    13; eop:    14; out1:  15; out2:   4
> branch: # 15; line:    10-   10; sop:    15; eop:    19; out1:  -2
> path #1: 0, 13, 15, 
> path #2: 0, 13, 4, 9, 11, 13, 15, 
> path #3: 0, 13, 4, 9, 6, 9, 11, 13, 15, 

它($a += $b(只是使用不同的,稍慢(!(的路径。是的,更慢:我的测试给出了 17 秒。 $a = $a + $b 秒和 20 秒。 $a += $b.不多,虽然很重要。而且与JavaScript也没有太大区别。

对于您的 PHP 版本来说,两分钟是相当大的,即使是旧的 PHP-5 在这里也能在 40 秒内完成。我在 ChangLogs 中找不到任何内容,但如果可能的话,您可以尝试更新。或者,如果您自己编译,请尝试不同的优化,因为MAC仍然与"普通"PC不同。