如何测量 Nodejs 中的事件循环阻塞?
How to measure Event loop blocking in Nodejs?
我无法获得真正的事件循环阻塞时间。我搜索了 Google 个答案 (),但它们对我没有帮助。我得到了不同的结果。
我已经创建了 Node/Express 应用程序。并尝试使用不同的工具检测事件循环阻塞。我用了hrtime, pm2, blocked_at.
1 次测试:
server.js
require('./routes')(app, passport, mongoData)
routes/index.js
router
.get('/articles/:articleId(\d+)', (req, res, next) => {
const blockedAt = require('blocked-at')
blockedAt((time, stack) => {
console.log(`Blocked for ${time}ms, operation started here:`, stack)
}, {threshold:12})
// my blocking script
for (let i = 0; i <= 1000000000; i++) {
let z = 10000 / Math.random()
}
let ArticleController = require(path + 'app/controllers/ArticleController')
let articleController = new ArticleController()
articleController.index(req, res, next)
})
我得到了:
Blocked for 15.5994921875ms, operation started here: [ ' at ',
' at ArticleService.getArticle (/app/services/article/ArticleService.js:79:44)' ]
Blocked for 14.0350537109375ms, operation started here: [ ' at Promise.then ()',
' at ExpressHandlebars.render (node_modules/express-handlebars/lib/express-handlebars.js:157:8)',
' at ExpressHandlebars. (node_modules/express-handlebars/lib/express-handlebars.js:226:29)' ]
但我的阻止脚本没有任何问题!
2 测试:
使用 pm2:
- 事件循环延迟 - 0.56 毫秒
- 事件循环延迟 p95 - 4.5 毫秒
删除阻止脚本后,我得到了相同的结果。
3 测试:
我用 hrtime 在里面测量 ArticleController.index。 Index 方法以异步模式加载 3 个服务。有很多I/O操作,有worker_threads有效。一些代码创建到 setImmediate 中。
里面进入索引:
let hrstart = process.hrtime()
// there works all my services
//...
let hrend = process.hrtime(hrstart)
console.info('Execution time (hr): %ds ir ms: %dms', hrend[0], hrend[1] / 1000000)
res.render('home', data)
我得到了 1 秒,233 毫秒。我玩得很开心,但我很困惑——因为所有操作都在异步模式下工作,事件循环不会阻塞吗?
如何测量事件循环块?
我期望输出:"event loop blocking in routes/index.js:12 for 5000ms",但实际输出没有捕捉到我的阻塞脚本。
你阻塞事件循环的时间就是你顺序处理的时间。对于您的示例,这将是该函数的主体。所以你可以只计时并将它添加到变量中。
let totalBlocked = 0;
router
.get('/articles/:articleId(\d+)', (req, res, next) => {
const start = new Date().getTime();
// my blocking script
for (let i = 0; i <= 1000000000; i++) {
let z = 10000 / Math.random() ;
}
let ArticleController = require(path + 'app/controllers/ArticleController');
let articleController = new ArticleController();
articleController.index(req, res, next);
const total = new Date().getTime() - start;
totalBlocked += total;
console.log(`Blocked for ${total}. Total blocked time is ${totalBlocked}`);
});
您还可以使用节点 perf_hooks
进行高分辨率计时。
const {performance } = require('perf_hooks');
let totalBlocked = 0;
router
.get('/articles/:articleId(\d+)', (req, res, next) => {
const start = performance.now();
// Do stuff
const total = performance.now() - start;
totalBlocked += total;
console.log(`Blocked for ${total}. Total blocked time is ${totalBlocked}`);
});
我无法获得真正的事件循环阻塞时间。我搜索了 Google 个答案 (
我已经创建了 Node/Express 应用程序。并尝试使用不同的工具检测事件循环阻塞。我用了hrtime, pm2, blocked_at.
1 次测试:
server.js
require('./routes')(app, passport, mongoData)
routes/index.js
router
.get('/articles/:articleId(\d+)', (req, res, next) => {
const blockedAt = require('blocked-at')
blockedAt((time, stack) => {
console.log(`Blocked for ${time}ms, operation started here:`, stack)
}, {threshold:12})
// my blocking script
for (let i = 0; i <= 1000000000; i++) {
let z = 10000 / Math.random()
}
let ArticleController = require(path + 'app/controllers/ArticleController')
let articleController = new ArticleController()
articleController.index(req, res, next)
})
我得到了:
Blocked for 15.5994921875ms, operation started here: [ ' at ', ' at ArticleService.getArticle (/app/services/article/ArticleService.js:79:44)' ] Blocked for 14.0350537109375ms, operation started here: [ ' at Promise.then ()', ' at ExpressHandlebars.render (node_modules/express-handlebars/lib/express-handlebars.js:157:8)', ' at ExpressHandlebars. (node_modules/express-handlebars/lib/express-handlebars.js:226:29)' ]
但我的阻止脚本没有任何问题!
2 测试:
使用 pm2:
- 事件循环延迟 - 0.56 毫秒
- 事件循环延迟 p95 - 4.5 毫秒
删除阻止脚本后,我得到了相同的结果。
3 测试:
我用 hrtime 在里面测量 ArticleController.index。 Index 方法以异步模式加载 3 个服务。有很多I/O操作,有worker_threads有效。一些代码创建到 setImmediate 中。
里面进入索引:
let hrstart = process.hrtime()
// there works all my services
//...
let hrend = process.hrtime(hrstart)
console.info('Execution time (hr): %ds ir ms: %dms', hrend[0], hrend[1] / 1000000)
res.render('home', data)
我得到了 1 秒,233 毫秒。我玩得很开心,但我很困惑——因为所有操作都在异步模式下工作,事件循环不会阻塞吗?
如何测量事件循环块?
我期望输出:"event loop blocking in routes/index.js:12 for 5000ms",但实际输出没有捕捉到我的阻塞脚本。
你阻塞事件循环的时间就是你顺序处理的时间。对于您的示例,这将是该函数的主体。所以你可以只计时并将它添加到变量中。
let totalBlocked = 0;
router
.get('/articles/:articleId(\d+)', (req, res, next) => {
const start = new Date().getTime();
// my blocking script
for (let i = 0; i <= 1000000000; i++) {
let z = 10000 / Math.random() ;
}
let ArticleController = require(path + 'app/controllers/ArticleController');
let articleController = new ArticleController();
articleController.index(req, res, next);
const total = new Date().getTime() - start;
totalBlocked += total;
console.log(`Blocked for ${total}. Total blocked time is ${totalBlocked}`);
});
您还可以使用节点 perf_hooks
进行高分辨率计时。
const {performance } = require('perf_hooks');
let totalBlocked = 0;
router
.get('/articles/:articleId(\d+)', (req, res, next) => {
const start = performance.now();
// Do stuff
const total = performance.now() - start;
totalBlocked += total;
console.log(`Blocked for ${total}. Total blocked time is ${totalBlocked}`);
});