看到哔哩哔哩有个视频对比golang和webman helloword压力测试性能,webman比goloang低了很多,低我理解,golang毕竟多线程自带协程,而且webman是框架,golang是http标准库,不在一个层次,但是感觉不会低这么多才对。还有我觉得应该是golang的http标准库和workerman对比才公平。所以我特地买了台aliyun服务器测试下,顺便把swoole workerman也压测了下,结果也发到了群里,既然测试了就记录下来给大家参考下,代码都有大家可以自行测试。
4核(vCPU) 4 GiB Ubuntu 20.04 64位
PHP 7.4.3
Go version go1.13.8 linux/amd64
ab -n100000 -c200 http://127.0.0.1:xxx/
没开keepalive
ab -n100000 -c200 -k http://127.0.0.1:xxx/
开了keepalive
对go不熟悉,不知道go怎么开多进程,为了公平起见我默认workerman webman swoole 全部1个进程,go就是教程里的helloword代码,应该也是一个进程,是不是多线程我不知道。
没开keepalive | 开了keepalive | |
---|---|---|
golang | 19995 | 98546 |
workerman | 30120 | 125986 |
webman | 29301 | 85938 |
swoole | 25836 | 73304 |
swoole+协程 | 27093 | 54596 |
结果是workeman压测性能高于golang,webman短连接高于golang,keepalive长连接略低于golang。
swoole短连接高于golang,keepalive低于golang。workerman和webman不管是短连接还是keepliave都高于swoole。
package main
import (
"net/http"
)
func handler(w http.ResponseWriter,r *http.Request) {
w.Write([]byte("hello"))
}
func main() {
http.HandleFunc("/",handler)
http.ListenAndServe(":8080",nil)
}
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
$worker = new Worker('http://0.0.0.0:12345');
$worker->onMessage = function($connection, $request)
{
// 不加-k参数时要用close才行?
$connection->close('hello');
};
Worker::runAll();
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
$worker = new Worker('http://0.0.0.0:12345');
$worker->onMessage = function($connection, $request)
{
// 不加-k时用send
$connection->send('hello');
};
Worker::runAll();
workerman这里不太好,ab测试时-k 参数需要自己区别处理,所以需要两个脚本
<?php
namespace app\controller;
use support\Request;
class Index
{
public function index(Request $request)
{
return 'hello';
}
}
<?php
$http = new Swoole\Http\Server('0.0.0.0', 12346, SWOOLE_BASE);
$http->on('Request', function ($request, $response) {
$response->end('hello');
});
$http->start();
<?php
use Swoole\Coroutine\Http\Server;
use function Swoole\Coroutine\run;
run(function () {
$server = new Server('127.0.0.1', 9502, false);
$server->handle('/', function ($request, $response) {
$response->end("hello");
});
$server->start();
});










我知道肯定会有人说helloword压测没有意义,但是我觉得还有一定意义的,毕竟代表了框架的极限性能啊。
https://learnku.com/laravel/t/63523
另外这里也有一个golang框架与webman的比较,带简单业务的,大家也可以参考的
支持一下
亲测单进程11w++
hellword不能代表什么,但是连helloword都不行,那...
第二,框架选择并不是最先进最好,而是最适合团队的,团队易用性,协作,门槛等等。
许多知名的软件依然是最稳定的,而不是最先进的
+1
这里我有必要说一下,PHP好在开发效率上,综合下来,性能够用、开发迅速;
golang的http库更像php-fpm,fast-http在地位上有点类似workerman,golang的web开发框架里利用了http-fast且支持fork多进程的框架fiber,还有个evio库和gnet库是类似于workerman但更低层,更像一个libevent、libuv、libev
比来比去没用,用适合的语言干适合的事,高效完成任务工作,才是应该干的事
感兴趣的人可以试一下gnet网络库
现在不是流行协程+epoll吗
你这个测试不具备实际的参考意义,真实的web应用业务场景是io密集型的,io操作是影响性能的关键,我在真实业务的测试结果是golang(gin)>swoole(hyperf)>workerman(webman),不信你可以试试,在一个接口中查几次数据库,插入或修改数据,然后写入一条日志,协程在处理io机密性操作还是有优势的,阻塞了会自动切换,要不然swoole花这么多精力搞个协程有什么意义呢
协程不具备并发能力,协程只是调度,协程需要结合线程,swoole是单线程,golang是多线程;swoole和libco应该有渊源关系;
另外您所谓的真实业务也需要建立在这几次查询数据库和插入及修改是否是原子性、是否有关联等前提下,顺带一提,gin+gorm的性能其实不如webman和hyperf;在重查询的实际项目中gorm+gin的组合的结果大约是hyperf、webman的80%,在重更新的实际项目中大约是hyperf、webman的105%左右,前提是webman使用常驻单例的数据库连接。
这个实际项目中还需要考虑是否有过重的json序列化需求,如果结合json序列化,golang所谓的性能及开发效率还要大打折扣
如果喜欢golang,我比较推荐一个基于fasthttp的框架fiber,这个框架包含了高性能orm及周边插件;如果是涉及到游戏服务开发,我推荐gnet网络框架。
如果请求中有需要访问第三方接口的情况,比如2s才返回结果,那么webman的性能应该就不如自带协程的golang了吧,不阻塞的情况下webman性能确实不错
类似的,golang用的线程池,和worker用多进程差不太多,线程更方便管理和弹性,但开多了一样的,区别不大;实际上整个生命周期属于阻塞队列
chaz6chez 说的很对,golang在重业务下很糟糕,我们将php项目转成了go,逻辑照搬,跑起来很差,fiber比gin要强很多,两个框架我们都上了,最后放弃go了
@army 为什么?
@Tinywan 初步断定为json的问题,起初用自带的库能干到CPU80%,换成sonic后好了很多,但还是不理想,还不如phpfpm, 其实qps500不算大,但是go表现真的不佳,不带业务或者业务小确实很流弊。
好吧!没用过go,有webman,基本够了,webman+fpm完全够用了
花了几天时间也用workerman重构了,今天在本地带业务压测,是原来php-fpm的6倍,感觉很棒,看线上效果了
可以的
webman够用了 多花点精力在数据库上
协程不具备并发这不是瞎扯嘛
从这个我感觉就只能说明golang不用多线程并且线程数一样是比不过,但是如果golang用多线程,并且多进程情况下肯定更快
没有可比性,我用jmeter深度测试过workerman和springboot 纯hello world 前者是快,原因在于 wm的request,session等等组件的封装其实很原生,做的并不多。而主流的框架,对请求要进行很多业务的封装,比如依赖注入,响应类型的自动处理,aop切面等等 一系列的业务。
我有个项目使用go开发的,目前正常使用中,在我本地调试 ,同样的请求同样的逻辑,go是10ms 而webman是25ms左右,我挺想把go改成webman的(已经重构10%),因为go我不太熟悉,开发速度很慢,也受不了不停的err判断,但是说句实在话,速度真的比webman 要快很多,webman已经开启了常驻内存
而且go的base64解密有问题,=号如果没处理好变成%3D ,就解不出来,php没问题,写一句一个err,简直一万个卧槽
先说结论
都不使用orm的情况下使用sql查询
webman(1.78万QPS)>swoole(1.30万QPS)>gin(0.80万QPS)
结果与第三方techempower压测跑分百分比基本一致
硬件
4核4G阿里云,ubuntu 22.04 64位
压测命令
环境
PHP 8.1
swoole 5.0.3
go 1.20.5
webman
进程数
cpu*4
,阻塞调用无连接池swoole
进程数 4,协程+连接池
go(gin)
多线程+协程+连接池
业务
随机从user表查询一条记录json形式返回给客户端。用户表10万条记录。
压测结果
webman
swoole
go(gin)
代码
webman
swoole
go(gin)
生成user表的代码
techempower 第三方压测数据
另外附上第三方压测数据,感觉他们压测的更专业
https://www.techempower.com/benchmarks/#section=data-r21&hw=ph&test=db&l=zijnjz-6bj&a=2&f=1ekg-cbcw-2t4w-27wr68-pc0-iv9slc-0-1ekgw-39g-kxs00-o0zk-5jsemh-2x8doc-2
一次数据库查询
多次数据库查询
数据库查询加更新
数据库更新
不带业务的helloworld
其它说明
同时我测试了webman下使用原生PDO和使用orm的性能差别
如果使用原生PDO
webman QPS为1.78万
如果使用laravel的Db::table()
webman QPS降到 0.94万QPS
如果使用laravel的Model
webmanQPS降到 0.72万QPS
可见,orm库对性能影响很大,性能最多相差2倍多。
可能这就是为什么有人测试webman 高于 gin,有人测试webman低于gin,因为没有在同一个层面去压测。
webman 1.78W QPS 对比 go(gin)的0.80W QPS 是合理的对比。
不过不管怎么样,webman性能不输go的框架,甚至一些情况下比go的框架性能好很多。
当然性能不是唯一指标,简单、好用、稳定、社区活跃、性能好这几点要找到一个平衡。
至于框架间性能那点区别,加点硬件就完事了,早点下班它不香吗?
试试go也和workerman一样使用事件库,而不是他内置的