Last active
May 4, 2016 07:18
-
-
Save lpinca/389b2fb022eee147d11a to your computer and use it in GitHub Desktop.
Compare different WebSocket modules echoing big and small buffers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const deflate = require('permessage-deflate'); | |
const Faye = require('faye-websocket'); | |
const http = require('http'); | |
exports.echo = opts => { | |
const messages = opts.messages; | |
const length = messages.length; | |
const extensions = []; | |
let count = 0; | |
let start; | |
if (opts.perMessageDeflate) extensions.push(deflate); | |
const server = http.createServer(); | |
server.on('upgrade', (req, socket, head) => { | |
const ws = new Faye(req, socket, head, null, { | |
maxLength: Infinity, | |
extensions | |
}); | |
ws.on('message', data => ws.send(data)); | |
}); | |
return new Promise(resolve => { | |
server.listen(() => { | |
const ws = new Faye.Client(`ws://localhost:${server.address().port}`, null, { | |
maxLength: Infinity, | |
extensions | |
}); | |
ws.on('open', () => { | |
start = Date.now(); | |
messages.forEach(message => ws.send(message)); | |
}); | |
ws.on('message', () => { | |
if (++count !== length) return; | |
const elapsed = (Date.now() - start) / 1000; | |
ws.close(); | |
server.close(() => resolve({ | |
rate: opts.size / elapsed, | |
time: elapsed | |
})); | |
}); | |
}); | |
}); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const prettyBytes = require('pretty-bytes'); | |
const crypto = require('crypto'); | |
const faye = require('./faye'); | |
const uws = require('./uws'); | |
const ws = require('./ws'); | |
const print = process.stderr.write.bind(process.stderr); | |
const size = 100 * 1024 * 1024; | |
const bigBufferOptions = { messages: [crypto.randomBytes(size)], size }; | |
const smallBuffersOptions = { messages: [], size: 0 }; | |
let i = 10000; | |
while (i--) { | |
const size = Math.floor(Math.random() * 1000) + 1; | |
smallBuffersOptions.messages.push(crypto.randomBytes(size)); | |
smallBuffersOptions.size += size; | |
} | |
const benchmarks = [ | |
{ | |
opts: Object.assign({ perMessageDeflate: false }, bigBufferOptions), | |
name: 'big buffer (ws)', | |
fn: ws.echo | |
}, | |
{ | |
opts: Object.assign({ perMessageDeflate: false }, bigBufferOptions), | |
name: 'big buffer (faye)', | |
fn: faye.echo | |
}, | |
{ | |
opts: Object.assign({ perMessageDeflate: false }, bigBufferOptions), | |
name: 'big buffer (uws)', | |
fn: uws.echo | |
}, | |
{ | |
opts: Object.assign({ perMessageDeflate: false }, smallBuffersOptions), | |
name: 'small buffers (ws)', | |
fn: ws.echo | |
}, | |
{ | |
opts: Object.assign({ perMessageDeflate: false }, smallBuffersOptions), | |
name: 'small buffers (faye)', | |
fn: faye.echo | |
}, | |
{ | |
opts: Object.assign({ perMessageDeflate: false }, smallBuffersOptions), | |
name: 'small buffers (uws)', | |
fn: uws.echo | |
}, | |
{ | |
opts: Object.assign({ perMessageDeflate: true }, bigBufferOptions), | |
name: 'big buffer permessage-deflate (ws)', | |
fn: ws.echo | |
}, | |
{ | |
opts: Object.assign({ perMessageDeflate: true }, bigBufferOptions), | |
name: 'big buffer permessage-deflate (faye)', | |
fn: faye.echo | |
}, | |
{ | |
opts: Object.assign({ perMessageDeflate: true }, smallBuffersOptions), | |
name: 'small buffers permessage-deflate (ws)', | |
fn: ws.echo | |
}, | |
{ | |
opts: Object.assign({ perMessageDeflate: true }, smallBuffersOptions), | |
name: 'small buffers permessage-deflate (faye)', | |
fn: faye.echo | |
} | |
]; | |
benchmarks.reduce((p, benchmark) => { | |
return p.then(data => { | |
if (data) print(`${data.time.toFixed(2)}s ${prettyBytes(data.rate)}/s\n`); | |
print(`${benchmark.name}: `); | |
return benchmark.fn.call(null, benchmark.opts); | |
}); | |
}, Promise.resolve()) | |
.then(data => print(`${data.time.toFixed(2)}s ${prettyBytes(data.rate)}/s\n`)) | |
.catch(err => console.error(err.stack)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "echo", | |
"version": "1.0.0", | |
"description": "Compare different WebSocket modules echoing big and small buffers", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"author": "Luigi Pinca", | |
"license": "ISC", | |
"main": "index.js", | |
"dependencies": { | |
"bufferutil": "^1.2.1", | |
"faye-websocket": "^0.11.0", | |
"permessage-deflate": "^0.1.5", | |
"pretty-bytes": "^3.0.1", | |
"utf-8-validate": "^1.2.1", | |
"uws": "^0.3.0", | |
"ws": "^1.0.1" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const uws = require('uws').uws; | |
const ws = require('ws'); | |
let port = 1023; | |
exports.echo = opts => { | |
const messages = opts.messages; | |
const length = messages.length; | |
let count = 0; | |
let start; | |
const server = new uws.Server(++port); | |
server.onMessage((socket, data, binary) => server.send(socket, data, binary)); | |
return new Promise(resolve => { | |
const socket = new ws(`ws://localhost:${port}`, { | |
perMessageDeflate: opts.perMessageDeflate | |
}); | |
socket.on('open', () => { | |
start = Date.now(); | |
messages.forEach(message => socket.send(message)); | |
}); | |
socket.on('message', () => { | |
if (++count !== length) return; | |
const elapsed = (Date.now() - start) / 1000; | |
socket.close(); | |
server.close(); | |
resolve({ | |
rate: opts.size / elapsed, | |
time: elapsed | |
}); | |
}); | |
}); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const http = require('http'); | |
const ws = require('ws'); | |
exports.echo = opts => { | |
const server = http.createServer(); | |
const messages = opts.messages; | |
const length = messages.length; | |
let count = 0; | |
let start; | |
const wss = new ws.Server({ | |
perMessageDeflate: opts.perMessageDeflate, | |
clientTracking: false, | |
server | |
}); | |
wss.on('connection', socket => { | |
socket.on('message', data => socket.send(data)); | |
}); | |
return new Promise(resolve => { | |
server.listen(() => { | |
const socket = new ws(`ws://localhost:${server.address().port}`, { | |
perMessageDeflate: opts.perMessageDeflate | |
}); | |
socket.on('open', () => { | |
start = Date.now(); | |
messages.forEach(message => socket.send(message)); | |
}); | |
socket.on('message', () => { | |
if (++count !== length) return; | |
const elapsed = (Date.now() - start) / 1000; | |
socket.close(); | |
server.close(() => resolve({ | |
rate: opts.size / elapsed, | |
time: elapsed | |
})); | |
}); | |
}); | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment