Add etf encoding support with erlpack (#943)

* the performance from this is astounding

* help uws

* save 15 bytes in webpacks

* update readme

* why is markdown like this

* optimizations

* Update WebSocketManager.js
This commit is contained in:
Gus Caplan
2016-12-02 20:35:59 -06:00
committed by Schuyler Cebulskie
parent 58c7c2e7b8
commit 1e5afc1608
4 changed files with 26 additions and 7 deletions

View File

@@ -27,7 +27,8 @@ Usability and performance are key focuses of discord.js, and it also has nearly
Without voice support: `npm install discord.js --save` Without voice support: `npm install discord.js --save`
With voice support ([node-opus](https://www.npmjs.com/package/node-opus)): `npm install discord.js node-opus --save` With voice support ([node-opus](https://www.npmjs.com/package/node-opus)): `npm install discord.js node-opus --save`
With voice support ([opusscript](https://www.npmjs.com/package/opusscript)): `npm install discord.js opusscript --save` With voice support ([opusscript](https://www.npmjs.com/package/opusscript)): `npm install discord.js opusscript --save`
With fast websockets ([uws](https://www.npmjs.com/package/uws)) `npm install discord.js uws --save` With a fast websocket client ([uws](https://www.npmjs.com/package/uws)) `npm install discord.js uws --save`
With fast websocket encoding ([erlpack](https://github.com/hammerandchisel/erlpack)) `npm install disscord.js hammerandchisel/erlpack --save`
The preferred audio engine is node-opus, as it performs significantly better than opusscript. When both are available, discord.js will automatically choose node-opus. The preferred audio engine is node-opus, as it performs significantly better than opusscript. When both are available, discord.js will automatically choose node-opus.
Using opusscript is only recommended for development environments where node-opus is tough to get working. Using opusscript is only recommended for development environments where node-opus is tough to get working.

View File

@@ -37,6 +37,7 @@
"ws": "^1.1.1" "ws": "^1.1.1"
}, },
"peerDependencies": { "peerDependencies": {
"erlpack": "github:hammerandchisel/erlpack",
"node-opus": "^0.2.0", "node-opus": "^0.2.0",
"opusscript": "^0.0.1", "opusscript": "^0.0.1",
"uws": "^0.11.1" "uws": "^0.11.1"
@@ -58,6 +59,7 @@
"browser": { "browser": {
"ws": false, "ws": false,
"uws": false, "uws": false,
"erlpack": false,
"opusscript": false, "opusscript": false,
"node-opus": false, "node-opus": false,
"tweet-nacl": false, "tweet-nacl": false,

View File

@@ -38,7 +38,7 @@ class RESTMethods {
getGateway() { getGateway() {
return this.rest.makeRequest('get', Constants.Endpoints.gateway, true).then(res => { return this.rest.makeRequest('get', Constants.Endpoints.gateway, true).then(res => {
this.rest.client.ws.gateway = `${res.url}/?encoding=json&v=${Constants.PROTOCOL_VERSION}`; this.rest.client.ws.gateway = `${res.url}/?v=${Constants.PROTOCOL_VERSION}`;
return this.rest.client.ws.gateway; return this.rest.client.ws.gateway;
}); });
} }

View File

@@ -1,6 +1,7 @@
const browser = typeof window !== 'undefined'; const browser = typeof window !== 'undefined';
const EventEmitter = require('events').EventEmitter; const EventEmitter = require('events').EventEmitter;
const Constants = require('../../util/Constants'); const Constants = require('../../util/Constants');
const convertArrayBuffer = require('../../util/ConvertArrayBuffer');
const pako = require('pako'); const pako = require('pako');
const zlib = require('zlib'); const zlib = require('zlib');
const PacketManager = require('./packets/WebSocketPacketManager'); const PacketManager = require('./packets/WebSocketPacketManager');
@@ -16,6 +17,15 @@ if (browser) {
} }
} }
let erlpack, serialize;
try {
erlpack = require('erlpack');
serialize = erlpack.pack;
} catch (err) {
erlpack = null;
serialize = JSON.stringify;
}
/** /**
* The WebSocket Manager of the Client * The WebSocket Manager of the Client
* @private * @private
@@ -100,6 +110,7 @@ class WebSocketManager extends EventEmitter {
} }
connect(gateway) { connect(gateway) {
gateway = `${gateway}&encoding=${erlpack ? 'etf' : 'json'}`;
if (this.first) { if (this.first) {
this._connect(gateway); this._connect(gateway);
this.first = false; this.first = false;
@@ -115,10 +126,10 @@ class WebSocketManager extends EventEmitter {
*/ */
send(data, force = false) { send(data, force = false) {
if (force) { if (force) {
this._send(JSON.stringify(data)); this._send(serialize(data));
return; return;
} }
this._queue.push(JSON.stringify(data)); this._queue.push(serialize(data));
this.doQueue(); this.doQueue();
} }
@@ -240,9 +251,14 @@ class WebSocketManager extends EventEmitter {
* @returns {Object} * @returns {Object}
*/ */
parseEventData(data) { parseEventData(data) {
if (data instanceof ArrayBuffer) data = pako.inflate(data, { to: 'string' }); if (erlpack) {
else if (data instanceof Buffer) data = zlib.inflateSync(data).toString(); if (data instanceof ArrayBuffer) data = convertArrayBuffer(data);
return JSON.parse(data); return erlpack.unpack(data);
} else {
if (data instanceof ArrayBuffer) data = pako.inflate(data, { to: 'string' });
else if (data instanceof Buffer) data = zlib.inflateSync(data).toString();
return JSON.parse(data);
}
} }
/** /**