php7 怎么比 Java 还快?

2019-09-23 11:22:47 +08:00
 zjsxwc

有点反认知,分别用 PHP 与 Java Spring Boot 写了个返回 1 个像素点图片的接口,结果 php 比 java 快。

代码

PHP 代码

<?php
//xpng.php

header("Content-type: image/png");

echo base64_decode("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWP4////fwAJ+wP9CNHoHgAAAABJRU5ErkJggg==");

Java 代码

//XController.java

package com.abtest;

import java.util.Base64;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class XController {
    @RequestMapping("/x.png")
    public ResponseEntity<byte[]> xpng() {
        String onepointpngBase64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWP4////fwAJ+wP9CNHoHgAAAABJRU5ErkJggg==";
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.set("Content-type", "image/png");
        byte[] decodedValue = Base64.getDecoder().decode(onepointpngBase64);
        return new ResponseEntity<byte[]>(decodedValue, responseHeaders, HttpStatus.OK);
    }
}

开始测试

Server 分别 SpringBoot Jar 包自带的 Apache Tomcat/9.0.24

PHP 就是 PHP 7.0.33-0+deb9u1 (cli) 自带的低性能调试用 server (使用php -S localhost:7767 -t .运行)

AB 结果反直觉,PHP 居然比 Java 快

PHP 结果耗时 0.125 秒
$ ab -n 1000 -c 1000 "http://localhost:7767/xpng.php"
This is ApacheBench, Version 2.3 <$Revision: 1757674 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:       
Server Hostname:        localhost
Server Port:            7767

Document Path:          /xpng.php
Document Length:        70 bytes

Concurrency Level:      1000
Time taken for tests:   0.125 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      190000 bytes
HTML transferred:       70000 bytes
Requests per second:    8011.99 [#/sec] (mean)
Time per request:       124.813 [ms] (mean)
Time per request:       0.125 [ms] (mean, across all concurrent requests)
Transfer rate:          1486.60 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    6   5.5      8      14
Processing:     5   22  20.1     13      69
Waiting:        4   22  20.2     12      69
Total:          8   29  21.3     19      71

Percentage of the requests served within a certain time (ms)
  50%     19
  66%     24
  75%     37
  80%     62
  90%     68
  95%     70
  98%     70
  99%     70
 100%     71 (longest request)
Java 结果耗时 0.498 秒
$ ab -n 1000 -c 1000 "http://localhost:8080/x.png"
This is ApacheBench, Version 2.3 <$Revision: 1757674 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:       
Server Hostname:        localhost
Server Port:            8080

Document Path:          /x.png
Document Length:        70 bytes

Concurrency Level:      1000
Time taken for tests:   0.498 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      188000 bytes
HTML transferred:       70000 bytes
Requests per second:    2007.85 [#/sec] (mean)
Time per request:       498.046 [ms] (mean)
Time per request:       0.498 [ms] (mean, across all concurrent requests)
Transfer rate:          368.63 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   3.2      0      11
Processing:     5   73  63.3     48     237
Waiting:        3   64  56.7     41     194
Total:          5   74  66.0     48     247

Percentage of the requests served within a certain time (ms)
  50%     48
  66%     63
  75%     76
  80%     88
  90%    216
  95%    225
  98%    229
  99%    234
 100%    247 (longest request)
16825 次点击
所在节点    程序员
134 条回复
cloudzhou
2019-09-27 13:47:09 +08:00
@zhuzeitou 仅仅从代码分析的话,我的代码更符合优化逻辑
因为减少了 f * f > i or f > i / f 的乘除操作(通过增量计算开平方 sqrt )
不过这个题目挺有意思,让我发现一个简单的问题,可以这样的优化
larry123
2019-09-27 15:24:08 +08:00
我记得 Java 默认是解释执行 class,当代码变成热点代码后,会进行 JIT 编译。
zhuzeitou
2019-09-27 17:16:19 +08:00
@cloudzhou 恩,之前没想到,也没仔细看你的代码,的确这样更好呢

https://paste.ubuntu.com/p/FpY5kK9R3q/
这里 NthPrime 是你上面版本的函数,NthPrime2 是我刚才又修改的函数
然后在我这边的机器上,调整函数定义的顺序(定义的顺序,不是执行的顺序哦……),执行效果差异也很大……
cloudzhou
2019-09-27 17:46:54 +08:00
@zhuzeitou haha. 这道题目准备到此为止了。
我又发现一篇文章不错: https://dave.cheney.net/practical-go/presentations/gophercon-singapore-2019.html
crella
2019-11-10 11:54:30 +08:00
自己改了下算法,同环境原 node 算法 4200ms,原 ruby 算法太久了测不出。改良 ruby 算法 8525ms (从 8900 优化成 8500 真是伤透了心),不会 javascript。

https://paste.ubuntu.com/p/g7XWqJGRxp/
zjsxwc
2020-11-27 11:36:18 +08:00
今天 php8.0.0 发布,我在同一台电脑里测试同样的代码,变成 19 秒了
zjsxwc
2020-11-27 14:27:27 +08:00
由于 javascript nodejs 不能用 int64 所以没有意义,我就不写了


在 int64 的情况下,求第 300000 个质数耗时

python2.7 65.9 秒
python3.8 62.4 秒
ruby2.7 28.3 秒
php7.2 22 秒
php7.4 20 秒
php8.0 19 秒

golang 10 秒
c++ 9.4 秒
纯 c 9.2 秒
java 8.8 秒
zjsxwc
2020-11-27 14:38:36 +08:00
zjsxwc
2020-11-27 15:16:18 +08:00
zjsxwc
2020-11-28 09:02:06 +08:00
zjsxwc
2020-11-28 09:09:12 +08:00
@zjsxwc #124 的 php8 19 秒是没开启 jit 成绩,开启 jit 后 php8 达到 14.9 秒,如图

https://i.loli.net/2020/11/28/XhekKo1gyzvTHF6.png



由于 javascript nodejs 不能用 int64 所以没有意义,我就不写了


在 int64 的情况下,求第 300000 个质数耗时

python2.7 65.9 秒
python3.8 62.4 秒
ruby2.7 28.3 秒
php7.2 22 秒
php7.4 20 秒
php8.0 19 秒
php8.0 开启 jit 14.9 秒

golang 10 秒
c++ 9.4 秒
纯 c 9.2 秒
java 8.8 秒
zjsxwc
2020-11-28 09:17:37 +08:00
编译 php8.0 开启 jit 的指令

下载 php8 源代码后解压进目录
./configure --prefix=/home/wangchao/Develop/php8.0.0 --enable-opcache
make install
cp ./php.ini-production /home/wangchao/Develop/php8.0.0/lib/php.ini
把 php.ini 里 zend_extension=opcache 前的分号删掉

开 jit 跑 php 测试脚本
/home/wangchao/Develop/php8.0.0/bin/php -dopcache.enable_cli=1 -dopcache.jit_buffer_size=100M -dopcache.jit=1255 test.php
zjsxwc
2020-11-28 16:37:00 +08:00
pypy 可以达到 10 秒 老牌 jit 牛逼
zjsxwc
2021-11-26 08:27:26 +08:00
使用 kphp 把 php 编译成独立二进制可执行文件,在同一台机器上算质数,耗时 5 秒,比 golang 快

root@caaa15c3621c:/tmp/dev# ./kphp_out/cli
第 300000 个素数的值是:4256233 耗时 5351 毫秒 root@caaa15c3621c:/tmp/dev# ls PN.php pnmain.php
PN.php pnmain.php

源码:
https://paste.ubuntu.com/p/FfZx5bjR3f/

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/603272

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX