Node.js 异步性能与同步性能对比

时间:2021-12-25 05:15:01

前言

上周做了个分享,基于node.js的ECMAScript 6(es6)的应用。第一部分讲了node.js。其中引用到了很多地方都在说的:node.js的异步非阻塞模型能扛高并发,是构建高性能网站的利器。但是没有示例,大家也提出了很多疑问。所以今天在此补上一个简单的示例。

说明:下文中的同步是指:同步阻塞操作,异步是指:异步非阻塞操作。

同步与异步

多线程同步io操作示例图

Node.js 异步性能与同步性能对比

                    (图片来自网络)

nodejs异步io示例图

Node.js 异步性能与同步性能对比

                    (图片来自网络)

测试环境和工具:

windows 10 X64
node.js 5.3.0 下载地址
http_load (压力测试工具 100KB左右) Windows版本下载Linux版本下载地址

文件目录和步骤

1、node.js 同步异步性能测试运行文件 server.js
2、读写测试文件 jquery-1.8.2.min.js 与 server.js 同目录
3、运行server.js ,命令 node server.js
4、浏览器中查看页面可否访问 http://127.0.0.1:8888
5、运行http_load 查看性能差别

node.js 同步异步操作代码

同步和异步操作使用的是fs的readFileSync和readFile。server.js 如下所示:

//server.js
var fs = require('fs');
var http = require('http');

http.createServer(function(request, response){
response.writeHead(200, {
'Content-Type': 'text/plain'
});
var start = new Date().getTime();
//异步处理
//read back from the file
// fs.readFile('./jquery-1.8.2.min.js', function(err, data) {
// if (err) throw err;
// result = (new Date().getTime() - start ) + ' ms------'+data;
// response.end(result);
// });

//同步处理
var result = fs.readFileSync('./jquery-1.8.2.min.js','utf-8');
response.end((new Date().getTime() - start ) + ' ms------'+result);
}).listen(8888);

console.log('Server running at http://127.0.0.1:8888/');

压力测试

http_load 使用的介绍:

命令格式:http_load -p 并发访问进程数 -s 访问时间 需要访问的URL文件

参数其实可以*组合,参数之间的选择并没有什么限制。比如你写成http_load -parallel 5 -seconds

300 urls.txt也是可以的。我们把参数给大家简单说明一下。
-parallel 简写-p :含义是并发的用户进程数。
-fetches 简写-f :含义是总计的访问次数
-rate 简写-r :含义是每秒的访问频率
-seconds简写-s :含义是总计的访问时间

请将要测试的链接地址写在 urllist.txt 中
准备URL文件:urllist.txt,文件格式是每行一个URL,URL最好超过50-100个测试效果比较好.文件格式

测试语句

http_load -p 3000 -s 30 urllist.txt

参数了解了:说明执行了一个持续时间30秒的测试,每秒的频率为3000次。

测试结果对比

我们来看运行一条命令来看看它的返回结果,下面分了四种情况。

低并发(300次请求每秒,持续30秒)

1、同步操作结果

Node.js 异步性能与同步性能对比

2、异步操作的结果

Node.js 异步性能与同步性能对比

高并发(3000次请求每秒,持续30秒)

1、同步操作结果

Node.js 异步性能与同步性能对比

2、异步操作的结果

Node.js 异步性能与同步性能对比

最后一张图的结果分析:

1.49909 fetches, 140 max parallel, 239802e+9 bytes, in 30.0004 seconds
说明在上面的测试中运行了49909个请求,最大的并发进程数是140,总计传输的数据是239802e+9bytes,运行的时间是30.0004秒
2.48047.9 mean bytes/connection 说明每个连接平均传输的数据字节量为 48047.9 bytes
3.1663.61 fetches/sec, 7.99332e+07 bytes/sec
说明每秒的响应请求为 1663.61 ,每秒传递的数据为 7.99332e+07 bytes/sec
4.msecs/connect: 12.1416 mean, 382.968 max, 0.392 min说明每连接的平均响应时间是 12.1416 msecs(这里单位是毫秒)
,最大的响应时间 382.968 msecs,最小的响应时间 0.392 msecs
5.msecs/first-response: 13.904 mean, 396.654 max, 1.911 min 第一次响应的平均时间 63.5362 msecs,最大 396.654 ms ,最小 1.911
6、24573 bad byte counts 请求失败次数24573 次
7、HTTP response codes: code 200 – 25786 说明打开响应页面的类型,200 表示成功次数:25768,如果403或其他类型过多,那可能要注意是否系统遇到了瓶颈。

特殊说明:
1、测试结果中主要的指标是 fetches/sec、msecs/connect 这个选项,即服务器每秒能够响应的查询次数,用这个指标来衡量性能。
2、测试中 没有提供更高的每秒频率是因为http_load 报了个问题,最多运行 3197 个请求每秒。http_load:parallel may be at most 3197

总结

1、测试中node.js的异步和同步操作,http_load 发起的请求数目巨大,但是该数目在线性提高频率的情况下并不是线性增长,说明如此增长下去会慢慢遇到顶了。同步操作下每秒请求数目提高10倍,每秒请求数目接近翻倍。
2、最大的并发进程数目瓶颈 是143 左右,该值应该是固定值(估计与机器配置相关,大家可以验证一下)。
3、同步和异步操作 的每个连接平均传输的数据字节量 差异巨大有10倍的差距,同步操作和异步操作在并发量大幅增加,每个连接的平均字节变化不大。
4、每秒处理的请求数目有明显差异,低并发下异步操作每秒处理的请求量是同步操作的两倍,高并发下两者差异明显减小。同类型相比的话,同步操作提升明显,异步操作增长趋缓,但还是明显高于同步操作。
5、由于每秒处理的请求数目有明显差异,异步操作比同步操作多一个数量级,大约为20倍。
6、每个链接平均需要的毫秒数时间,同步大约是异步的10倍。最大值差异大,最小值差异小。
7、第一次响应平均需要的毫秒时间,低并发下,同步是异步操作的8.14被;大并发下,同步是异步的 3.5倍;
8、低并发下:同步请求成功率794/20240*100% = 3.92%, 异步请求成功率21772/41530*100% = 52.42%;高并发下:同步请求成功率1557/38011*100% = 4.096%,异步请求成功率25786/49909*100% = 51.66%;不同并发下,同类型的操作成功率差别不大,但是异步操作的成功率是同步操作的12.5倍左右。

一句话:异步操作在处理的性能上还是优于同步操作