Skip to content
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

Closed
wants to merge 38 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
442ba7f
squash commit from ws
eljefedelrodeodeljefe Jan 17, 2016
c955812
ws: Do not run tests through make
eljefedelrodeodeljefe Jan 13, 2016
38c27f1
removes cpp deps
eljefedelrodeodeljefe Jan 13, 2016
fc8d1c0
deprecates make
eljefedelrodeodeljefe Jan 14, 2016
0951c85
have ultron included in websocket class file
eljefedelrodeodeljefe Jan 14, 2016
6ffce4a
deprecates ultron as external dep
eljefedelrodeodeljefe Jan 14, 2016
60205f9
Now native options parsing; fails one test TODO
eljefedelrodeodeljefe Jan 15, 2016
3fe34bc
style changes in WebSocketServer
eljefedelrodeodeljefe Jan 15, 2016
48098fa
removes Options as dep; style changes
eljefedelrodeodeljefe Jan 16, 2016
ad3bec9
add prototypical inheritance. prep for including definition
eljefedelrodeodeljefe Jan 16, 2016
1a45444
BufferUtil: refactor for style and prototypical inhertiance
eljefedelrodeodeljefe Jan 16, 2016
031bc3e
style: finish const-require in files
eljefedelrodeodeljefe Jan 16, 2016
26b5029
Receiver, Opcode handlers: refactor for more expressiveness
eljefedelrodeodeljefe Jan 16, 2016
743d3d8
extract opcodes into separate file -> prepping it as class
eljefedelrodeodeljefe Jan 16, 2016
e7563d6
opcodes: change for style
eljefedelrodeodeljefe Jan 16, 2016
f62fb0f
wording: callback -> cb
eljefedelrodeodeljefe Jan 16, 2016
9888a33
remove Validation as dep
eljefedelrodeodeljefe Jan 17, 2016
d968ccf
minor style and formatting in lib/
eljefedelrodeodeljefe Jan 17, 2016
e740602
refactor for node-core test structure
eljefedelrodeodeljefe Jan 18, 2016
30370b3
tests: ports to node-core compliant structure; no 'should'
eljefedelrodeodeljefe Jan 20, 2016
84575af
editing file structure to be core compatible
eljefedelrodeodeljefe Jan 21, 2016
794062a
changes file structure for node comppat, no external dep
eljefedelrodeodeljefe Jan 21, 2016
3bae80a
remove app files
eljefedelrodeodeljefe Jan 21, 2016
d175dec
remove examples from app repo
eljefedelrodeodeljefe Jan 21, 2016
96582c2
ports websockets docs. git mv
eljefedelrodeodeljefe Jan 21, 2016
5c9af45
ports benchmarks
eljefedelrodeodeljefe Jan 21, 2016
f954efa
remove integration tests
eljefedelrodeodeljefe Jan 21, 2016
56834d7
removes unnecessary module files
eljefedelrodeodeljefe Jan 21, 2016
9b45440
Subtree merge ws
eljefedelrodeodeljefe Jan 22, 2016
83e066e
ws: removes mocha as a dependency
eljefedelrodeodeljefe Jan 24, 2016
b776eae
ws: preapare for node-native-compile
eljefedelrodeodeljefe Jan 24, 2016
be2f314
ws: fixes requiring
eljefedelrodeodeljefe Jan 24, 2016
e5cc9d3
ws: tests require native module
eljefedelrodeodeljefe Jan 24, 2016
7d70efc
ws: move errorcodes into public module
eljefedelrodeodeljefe Jan 24, 2016
52cb084
ws: removes bufferutil class
eljefedelrodeodeljefe Jan 24, 2016
61090b8
ws: removes bufferpool as internal dep
eljefedelrodeodeljefe Jan 24, 2016
3a63d82
ws: removes unecessary api comments
eljefedelrodeodeljefe Jan 24, 2016
94153d7
ws: removes unecessary api doc and comments, blank lines
eljefedelrodeodeljefe Jan 25, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions benchmark/websockets/parser.benchmark.js
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')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

, Receiver = require('../').Receiver
, suite = new benchmark.Suite('Receiver');
require('tinycolor');
require('./util');

/**
* Setup receiver.
*/

suite.on('start', function () {
Copy link
Member

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add this to the known issues list. Haven't touched benchmark yet

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;
}
66 changes: 66 additions & 0 deletions benchmark/websockets/sender.benchmark.js
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;
}
105 changes: 105 additions & 0 deletions benchmark/websockets/speed.js
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);
})();
}
105 changes: 105 additions & 0 deletions benchmark/websockets/util.js
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;
}
Loading