noed ---- 性能检测和优化
一、NodeJS 的几种性能检测和优化的方法
(1)、确保 Node.js 是最新的Node版本
官网更新的 Node 版本 相较于上一个版本 无论在性能还是代码优化都有一定的提升
(2)、使用 fast-json-stringify 加速 JSON 序列化
在 JSON 序列化时,我们需要识别大量的字段类型,比如对于 string 类型,我们就需要在两边加上 "
,对于数组类型,我们需要遍历数组,把每个对象序列化后,用 ,
隔开,然后在两边加上 [
和 ]
, 诸如此类等等。
但如果已经提前通过 Schema 知道每个字段的类型,那么就不需要遍历、识别字段类型,而可以直接用序列化对应的字段,这就大大减少了计算开销,这就是 fast-json-stringfy 的原理。
实例:
const fastJson = require('fast-json-stringify')
const stringify = fastJson({
title: 'Example Schema',
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'integer' },
books: {
type: 'array',
items: {
type: 'string',
uniqueItems: true
}
}
}
})
console.log(stringify({
name: 'Starkwang',
age: 23,
books: ['C++ Primer', 'test']
}))
(3)、提升 Promise 的性能
promise 是解决前端回调地狱的目前最好办法 但是其对性能的消耗也是巨大的
所以对于大量异步逻辑、轻量计算的中间件项目而言,可以在代码中把全局的 Promise 换为 bluebird 的实现:
global.Promise = require('bluebird');
(4)、正确地编写异步代码
(1)、Promise.all()
的并行能力:
// 消耗性能的
async function getUserInfo(id) {
const profile = await getUserProfile(id);
const repo = await getUserRepo(id)
return { profile, repo }
}
// 优化后的
async function getUserInfo(id) {
const [profile, repo] = await Promise.all([
getUserProfile(id),
getUserRepo(id)
])
return { profile, repo }
}
(2)、Promise.any()
async function getServiceIP(name) {
// 从 DNS 和 ZooKeeper 获取服务 IP,哪个先成功返回用哪个
// 与 Promise.race 不同的是,这里只有当两个调用都 reject 时,才会抛出错误
return await Promise.any([
getIPFromDNS(name),
getIPFromZooKeeper(name)
])
}
(5)、优化 V8 GC
V8 的垃圾回收器是 stop-the-world/incremental/concurrent/parallel 兼而有之的,对垃圾回收的不同阶段做了不同的优化。它将 JavaScript 对象分为趋向于频繁诞生于死亡的新生代与常驻内存的老生代,使用不同的策略进行回收,来降低垃圾回收的开销。