Node.js
Node.jsのパフォーマンス
サーチ…
イベントループ
ブロッキング操作の例
let loop = (i, max) => {
while (i < max) i++
return i
}
// This operation will block Node.js
// Because, it's CPU-bound
// You should be careful about this kind of code
loop(0, 1e+12)
非ブロッキングIO操作の例
let i = 0
const step = max => {
while (i < max) i++
console.log('i = %d', i)
}
const tick = max => process.nextTick(step, max)
// this will postpone tick run step's while-loop to event loop cycles
// any other IO-bound operation (like filesystem reading) can take place
// in parallel
tick(1e+6)
tick(1e+7)
console.log('this will output before all of tick operations. i = %d', i)
console.log('because tick operations will be postponed')
tick(1e+8)
簡単に言えば、Event Loopは、実行を終了するまでCPUバインドコードを実行し、IOブロックコードを非ブロッキング形式で実行するシングルスレッドキューメカニズムです。
しかし、カーペットの下にあるNode.jsは、 libuvライブラリを通して、その操作のいくつかのためにマルチスレッドを使用します。
パフォーマンスに関する考慮事項
- ノンブロッキング操作はキューをブロックせず、ループのパフォーマンスに影響を与えません。
- ただし、CPUバウンド処理ではキューがブロックされるため、Node.jsコードでCPUバウンド処理を行わないように注意してください。
Node.jsは、オペレーティングシステムカーネルに作業負荷を負担させるためIOを非ブロックにし、IO操作がデータを( イベントとして )供給すると、指定されたコールバックでコードを通知します。
maxSocketsを増やす
基本
require('http').globalAgent.maxSockets = 25
// You can change 25 to Infinity or to a different value by experimenting
Node.jsはデフォルトでmaxSockets = Infinity
を同時に使用しています( v0.12.0以降)。ノードv0.12.0まで、デフォルトはmaxSockets = 5
でした ( v0.11.0参照)。したがって、5つ以上のリクエストの後、それらはキューに入れられます。並行性が必要な場合は、この数を増やしてください。
自分のエージェントを設定する
http
APIは「 グローバルエージェント 」を使用しています。あなた自身のエージェントを提供することができます。このような:
const http = require('http')
const myGloriousAgent = new http.Agent({ keepAlive: true })
myGloriousAgent.maxSockets = Infinity
http.request({ ..., agent: myGloriousAgent }, ...)
ソケットプールを完全に無効にする
const http = require('http')
const options = {.....}
options.agent = false
const request = http.request(options)
落とし穴
同じ効果が必要な場合は、
https
APIで同じことを行う必要がありhttps
たとえば、 AWSでは
Infinity
ではなく、50が使用されることに注意してください。
gzipを有効にする
const http = require('http')
const fs = require('fs')
const zlib = require('zlib')
http.createServer((request, response) => {
const stream = fs.createReadStream('index.html')
const acceptsEncoding = request.headers['accept-encoding']
let encoder = {
hasEncoder : false,
contentEncoding: {},
createEncoder : () => throw 'There is no encoder'
}
if (!acceptsEncoding) {
acceptsEncoding = ''
}
if (acceptsEncoding.match(/\bdeflate\b/)) {
encoder = {
hasEncoder : true,
contentEncoding: { 'content-encoding': 'deflate' },
createEncoder : zlib.createDeflate
}
} else if (acceptsEncoding.match(/\bgzip\b/)) {
encoder = {
hasEncoder : true,
contentEncoding: { 'content-encoding': 'gzip' },
createEncoder : zlib.createGzip
}
}
response.writeHead(200, encoder.contentEncoding)
if (encoder.hasEncoder) {
stream = stream.pipe(encoder.createEncoder())
}
stream.pipe(response)
}).listen(1337)
Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow