-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature: ws in core #4842
feature: ws in core #4842
Changes from all commits
442ba7f
c955812
38c27f1
fc8d1c0
0951c85
6ffce4a
60205f9
3fe34bc
48098fa
ad3bec9
1a45444
031bc3e
26b5029
743d3d8
e7563d6
f62fb0f
9888a33
d968ccf
e740602
30370b3
84575af
794062a
3bae80a
d175dec
96582c2
5c9af45
f954efa
56834d7
9b45440
83e066e
b776eae
be2f314
e5cc9d3
7d70efc
52cb084
61090b8
3a63d82
94153d7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
/*! | ||
* ws: a node.js websocket client | ||
* Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com> | ||
* MIT Licensed | ||
*/ | ||
|
||
/** | ||
* Benchmark dependencies. | ||
*/ | ||
|
||
var benchmark = require('benchmark') | ||
, Receiver = require('../').Receiver | ||
, suite = new benchmark.Suite('Receiver'); | ||
require('tinycolor'); | ||
require('./util'); | ||
|
||
/** | ||
* Setup receiver. | ||
*/ | ||
|
||
suite.on('start', function () { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. arrows, also for other declarations - might as well add modern code to core if it's going to be added. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll add this to the |
||
receiver = new Receiver(); | ||
}); | ||
|
||
suite.on('cycle', function () { | ||
receiver = new Receiver(); | ||
}); | ||
|
||
/** | ||
* Benchmarks. | ||
*/ | ||
|
||
var pingMessage = 'Hello' | ||
, pingPacket1 = getBufferFromHexString('89 ' + (pack(2, 0x80 | pingMessage.length)) + | ||
' 34 83 a8 68 '+ getHexStringFromBuffer(mask(pingMessage, '34 83 a8 68'))); | ||
suite.add('ping message', function () { | ||
receiver.add(pingPacket1); | ||
}); | ||
|
||
var pingPacket2 = getBufferFromHexString('89 00') | ||
suite.add('ping with no data', function () { | ||
receiver.add(pingPacket2); | ||
}); | ||
|
||
var closePacket = getBufferFromHexString('88 00'); | ||
suite.add('close message', function () { | ||
receiver.add(closePacket); | ||
receiver.endPacket(); | ||
}); | ||
|
||
var maskedTextPacket = getBufferFromHexString('81 93 34 83 a8 68 01 b9 92 52 4f a1 c6 09 59 e6 8a 52 16 e6 cb 00 5b a1 d5'); | ||
suite.add('masked text message', function () { | ||
receiver.add(maskedTextPacket); | ||
}); | ||
|
||
binaryDataPacket = (function() { | ||
var length = 125 | ||
, message = new Buffer(length) | ||
for (var i = 0; i < length; ++i) message[i] = i % 10; | ||
return getBufferFromHexString('82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' | ||
+ getHexStringFromBuffer(mask(message), '34 83 a8 68')); | ||
})(); | ||
suite.add('binary data (125 bytes)', function () { | ||
try { | ||
receiver.add(binaryDataPacket); | ||
|
||
} | ||
catch(e) {console.log(e)} | ||
}); | ||
|
||
binaryDataPacket2 = (function() { | ||
var length = 65535 | ||
, message = new Buffer(length) | ||
for (var i = 0; i < length; ++i) message[i] = i % 10; | ||
return getBufferFromHexString('82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' | ||
+ getHexStringFromBuffer(mask(message), '34 83 a8 68')); | ||
})(); | ||
suite.add('binary data (65535 bytes)', function () { | ||
receiver.add(binaryDataPacket2); | ||
}); | ||
|
||
binaryDataPacket3 = (function() { | ||
var length = 200*1024 | ||
, message = new Buffer(length) | ||
for (var i = 0; i < length; ++i) message[i] = i % 10; | ||
return getBufferFromHexString('82 ' + getHybiLengthAsHexString(length, true) + ' 34 83 a8 68 ' | ||
+ getHexStringFromBuffer(mask(message), '34 83 a8 68')); | ||
})(); | ||
suite.add('binary data (200 kB)', function () { | ||
receiver.add(binaryDataPacket3); | ||
}); | ||
|
||
/** | ||
* Output progress. | ||
*/ | ||
|
||
suite.on('cycle', function (bench, details) { | ||
console.log('\n ' + suite.name.grey, details.name.white.bold); | ||
console.log(' ' + [ | ||
details.hz.toFixed(2).cyan + ' ops/sec'.grey | ||
, details.count.toString().white + ' times executed'.grey | ||
, 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey | ||
, | ||
].join(', '.grey)); | ||
}); | ||
|
||
/** | ||
* Run/export benchmarks. | ||
*/ | ||
|
||
if (!module.parent) { | ||
suite.run(); | ||
} else { | ||
module.exports = suite; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/*! | ||
* ws: a node.js websocket client | ||
* Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com> | ||
* MIT Licensed | ||
*/ | ||
|
||
/** | ||
* Benchmark dependencies. | ||
*/ | ||
|
||
var benchmark = require('benchmark') | ||
, Sender = require('../').Sender | ||
, suite = new benchmark.Suite('Sender'); | ||
require('tinycolor'); | ||
require('./util'); | ||
|
||
/** | ||
* Setup sender. | ||
*/ | ||
|
||
suite.on('start', function () { | ||
sender = new Sender(); | ||
sender._socket = { write: function() {} }; | ||
}); | ||
|
||
suite.on('cycle', function () { | ||
sender = new Sender(); | ||
sender._socket = { write: function() {} }; | ||
}); | ||
|
||
/** | ||
* Benchmarks | ||
*/ | ||
|
||
framePacket = new Buffer(200*1024); | ||
framePacket.fill(99); | ||
suite.add('frameAndSend, unmasked (200 kB)', function () { | ||
sender.frameAndSend(0x2, framePacket, true, false); | ||
}); | ||
suite.add('frameAndSend, masked (200 kB)', function () { | ||
sender.frameAndSend(0x2, framePacket, true, true); | ||
}); | ||
|
||
/** | ||
* Output progress. | ||
*/ | ||
|
||
suite.on('cycle', function (bench, details) { | ||
console.log('\n ' + suite.name.grey, details.name.white.bold); | ||
console.log(' ' + [ | ||
details.hz.toFixed(2).cyan + ' ops/sec'.grey | ||
, details.count.toString().white + ' times executed'.grey | ||
, 'benchmark took '.grey + details.times.elapsed.toString().white + ' sec.'.grey | ||
, | ||
].join(', '.grey)); | ||
}); | ||
|
||
/** | ||
* Run/export benchmarks. | ||
*/ | ||
|
||
if (!module.parent) { | ||
suite.run(); | ||
} else { | ||
module.exports = suite; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
var cluster = require('cluster') | ||
, WebSocket = require('../') | ||
, WebSocketServer = WebSocket.Server | ||
, crypto = require('crypto') | ||
, util = require('util') | ||
, ansi = require('ansi'); | ||
require('tinycolor'); | ||
|
||
function roundPrec(num, prec) { | ||
var mul = Math.pow(10, prec); | ||
return Math.round(num * mul) / mul; | ||
} | ||
|
||
function humanSize(bytes) { | ||
if (bytes >= 1048576) return roundPrec(bytes / 1048576, 2) + ' MB'; | ||
if (bytes >= 1024) return roundPrec(bytes / 1024, 2) + ' kB'; | ||
return roundPrec(bytes, 2) + ' B'; | ||
} | ||
|
||
function generateRandomData(size) { | ||
var buffer = new Buffer(size); | ||
for (var i = 0; i < size; ++i) { | ||
buffer[i] = ~~(Math.random() * 127); | ||
} | ||
return buffer; | ||
} | ||
|
||
if (cluster.isMaster) { | ||
var wss = new WebSocketServer({port: 8181}, function() { | ||
cluster.fork(); | ||
}); | ||
wss.on('connection', function(ws) { | ||
ws.on('message', function(data, flags) { | ||
ws.send(data, {binary: flags&&flags.binary}); | ||
}); | ||
ws.on('close', function() {}); | ||
}); | ||
cluster.on('death', function(worker) { | ||
wss.close(); | ||
}); | ||
} | ||
else { | ||
var cursor = ansi(process.stdout); | ||
|
||
var configs = [ | ||
[true, 10000, 64], | ||
[true, 5000, 16*1024], | ||
[true, 1000, 128*1024], | ||
[true, 100, 1024*1024], | ||
[true, 1, 500*1024*1024], | ||
[false, 10000, 64], | ||
[false, 5000, 16*1024], | ||
[false, 1000, 128*1024], | ||
[false, 100, 1024*1024], | ||
]; | ||
|
||
var largest = configs[0][1]; | ||
for (var i = 0, l = configs.length; i < l; ++i) { | ||
if (configs[i][2] > largest) largest = configs[i][2]; | ||
} | ||
|
||
console.log('Generating %s of test data ...', humanSize(largest)); | ||
var randomBytes = generateRandomData(largest); | ||
|
||
function roundtrip(useBinary, roundtrips, size, cb) { | ||
var data = randomBytes.slice(0, size); | ||
var prefix = util.format('Running %d roundtrips of %s %s data', roundtrips, humanSize(size), useBinary ? 'binary' : 'text'); | ||
console.log(prefix); | ||
var client = new WebSocket('ws://localhost:' + '8181'); | ||
var dt; | ||
var roundtrip = 0; | ||
function send() { | ||
client.send(data, {binary: useBinary}); | ||
} | ||
client.on('error', function(e) { | ||
console.error(e); | ||
process.exit(); | ||
}); | ||
client.on('open', function() { | ||
dt = Date.now(); | ||
send(); | ||
}); | ||
client.on('message', function(data, flags) { | ||
if (++roundtrip == roundtrips) { | ||
var elapsed = Date.now() - dt; | ||
cursor.up(); | ||
console.log('%s:\t%ss\t%s' | ||
, useBinary ? prefix.green : prefix.cyan | ||
, roundPrec(elapsed / 1000, 1).toString().green.bold | ||
, (humanSize((size * roundtrips) / elapsed * 1000) + '/s').blue.bold); | ||
client.close(); | ||
cb(); | ||
return; | ||
} | ||
process.nextTick(send); | ||
}); | ||
} | ||
|
||
(function run() { | ||
if (configs.length == 0) process.exit(); | ||
var config = configs.shift(); | ||
config.push(run); | ||
roundtrip.apply(null, config); | ||
})(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/*! | ||
* ws: a node.js websocket client | ||
* Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com> | ||
* MIT Licensed | ||
*/ | ||
|
||
/** | ||
* Returns a Buffer from a "ff 00 ff"-type hex string. | ||
*/ | ||
|
||
getBufferFromHexString = function(byteStr) { | ||
var bytes = byteStr.split(' '); | ||
var buf = new Buffer(bytes.length); | ||
for (var i = 0; i < bytes.length; ++i) { | ||
buf[i] = parseInt(bytes[i], 16); | ||
} | ||
return buf; | ||
} | ||
|
||
/** | ||
* Returns a hex string from a Buffer. | ||
*/ | ||
|
||
getHexStringFromBuffer = function(data) { | ||
var s = ''; | ||
for (var i = 0; i < data.length; ++i) { | ||
s += padl(data[i].toString(16), 2, '0') + ' '; | ||
} | ||
return s.trim(); | ||
} | ||
|
||
/** | ||
* Splits a buffer in two parts. | ||
*/ | ||
|
||
splitBuffer = function(buffer) { | ||
var b1 = new Buffer(Math.ceil(buffer.length / 2)); | ||
buffer.copy(b1, 0, 0, b1.length); | ||
var b2 = new Buffer(Math.floor(buffer.length / 2)); | ||
buffer.copy(b2, 0, b1.length, b1.length + b2.length); | ||
return [b1, b2]; | ||
} | ||
|
||
/** | ||
* Performs hybi07+ type masking on a hex string or buffer. | ||
*/ | ||
|
||
mask = function(buf, maskString) { | ||
if (typeof buf == 'string') buf = new Buffer(buf); | ||
var mask = getBufferFromHexString(maskString || '34 83 a8 68'); | ||
for (var i = 0; i < buf.length; ++i) { | ||
buf[i] ^= mask[i % 4]; | ||
} | ||
return buf; | ||
} | ||
|
||
/** | ||
* Returns a hex string representing the length of a message | ||
*/ | ||
|
||
getHybiLengthAsHexString = function(len, masked) { | ||
if (len < 126) { | ||
var buf = new Buffer(1); | ||
buf[0] = (masked ? 0x80 : 0) | len; | ||
} | ||
else if (len < 65536) { | ||
var buf = new Buffer(3); | ||
buf[0] = (masked ? 0x80 : 0) | 126; | ||
getBufferFromHexString(pack(4, len)).copy(buf, 1); | ||
} | ||
else { | ||
var buf = new Buffer(9); | ||
buf[0] = (masked ? 0x80 : 0) | 127; | ||
getBufferFromHexString(pack(16, len)).copy(buf, 1); | ||
} | ||
return getHexStringFromBuffer(buf); | ||
} | ||
|
||
/** | ||
* Unpacks a Buffer into a number. | ||
*/ | ||
|
||
unpack = function(buffer) { | ||
var n = 0; | ||
for (var i = 0; i < buffer.length; ++i) { | ||
n = (i == 0) ? buffer[i] : (n * 256) + buffer[i]; | ||
} | ||
return n; | ||
} | ||
|
||
/** | ||
* Returns a hex string, representing a specific byte count 'length', from a number. | ||
*/ | ||
|
||
pack = function(length, number) { | ||
return padl(number.toString(16), length, '0').replace(/([0-9a-f][0-9a-f])/gi, '$1 ').trim(); | ||
} | ||
|
||
/** | ||
* Left pads the string 's' to a total length of 'n' with char 'c'. | ||
*/ | ||
|
||
padl = function(s, n, c) { | ||
return new Array(1 + n - s.length).join(c) + s; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const