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

dgram: support multiple buffers #4374

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,10 @@ bench-events: all
bench-util: all
@$(NODE) benchmark/common.js util

bench-all: bench bench-misc bench-array bench-buffer bench-url bench-events
bench-dgram: all
@$(NODE) benchmark/common.js dgram

bench-all: bench bench-misc bench-array bench-buffer bench-url bench-events bench-dgram bench-util

bench: bench-net bench-http bench-fs bench-tls

Expand Down
80 changes: 80 additions & 0 deletions benchmark/dgram/array-vs-concat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// test UDP send throughput with the multi buffer API against Buffer.concat
'use strict';

const common = require('../common.js');
const PORT = common.PORT;

// `num` is the number of send requests to queue up each time.
// Keep it reasonably high (>10) otherwise you're benchmarking the speed of
// event loop cycles more than anything else.
var bench = common.createBenchmark(main, {
len: [64, 256, 512, 1024],
num: [100],
chunks: [1, 2, 4, 8],
type: ['concat', 'multi'],
dur: [5]
});

var dur;
var len;
var num;
var type;
var chunk;
var chunks;
var encoding;

function main(conf) {
dur = +conf.dur;
len = +conf.len;
num = +conf.num;
type = conf.type;
chunks = +conf.chunks;

chunk = []
for (var i = 0; i < chunks; i++) {
chunk.push(new Buffer(Math.round(len / chunks)));
}

server();
}

var dgram = require('dgram');

function server() {
var sent = 0;
var received = 0;
var socket = dgram.createSocket('udp4');

var onsend = type === 'concat' ? onsendConcat : onsendMulti;

function onsendConcat() {
if (sent++ % num == 0)
for (var i = 0; i < num; i++) {
socket.send(Buffer.concat(chunk), PORT, '127.0.0.1', onsend);
}
}

function onsendMulti() {
if (sent++ % num == 0)
for (var i = 0; i < num; i++) {
socket.send(chunk, PORT, '127.0.0.1', onsend);
}
}

socket.on('listening', function() {
bench.start();
onsend();

setTimeout(function() {
var bytes = sent * len;
var gbits = (bytes * 8) / (1024 * 1024 * 1024);
bench.end(gbits);
}, dur * 1000);
});

socket.on('message', function(buf, rinfo) {
received++;
});

socket.bind(PORT);
}
70 changes: 70 additions & 0 deletions benchmark/dgram/multi-buffer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// test UDP send/recv throughput with the multi buffer API
'use strict';

const common = require('../common.js');
const PORT = common.PORT;

// `num` is the number of send requests to queue up each time.
// Keep it reasonably high (>10) otherwise you're benchmarking the speed of
// event loop cycles more than anything else.
var bench = common.createBenchmark(main, {
len: [64, 256, 1024],
num: [100],
chunks: [1, 2, 4, 8],
type: ['send', 'recv'],
dur: [5]
});

var dur;
var len;
var num;
var type;
var chunk;
var chunks;
var encoding;

function main(conf) {
dur = +conf.dur;
len = +conf.len;
num = +conf.num;
type = conf.type;
chunks = +conf.chunks;

chunk = []
for (var i = 0; i < chunks; i++) {
chunk.push(new Buffer(Math.round(len / chunks)));
}

server();
}

var dgram = require('dgram');

function server() {
var sent = 0;
var received = 0;
var socket = dgram.createSocket('udp4');

function onsend() {
if (sent++ % num == 0)
for (var i = 0; i < num; i++)
socket.send(chunk, PORT, '127.0.0.1', onsend);
}

socket.on('listening', function() {
bench.start();
onsend();

setTimeout(function() {
var bytes = (type === 'send' ? sent : received) * len;
var gbits = (bytes * 8) / (1024 * 1024 * 1024);
bench.end(gbits);
}, dur * 1000);
});

socket.on('message', function(buf, rinfo) {
received++;
});

socket.bind(PORT);
}
7 changes: 4 additions & 3 deletions benchmark/net/dgram.js → benchmark/dgram/offset-length.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// test UDP send/recv throughput
// test UDP send/recv throughput with the "old" offset/length API
'use strict';

var common = require('../common.js');
var PORT = common.PORT;
const common = require('../common.js');
const PORT = common.PORT;

// `num` is the number of send requests to queue up each time.
// Keep it reasonably high (>10) otherwise you're benchmarking the speed of
Expand Down
62 changes: 62 additions & 0 deletions benchmark/dgram/single-buffer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// test UDP send/recv throughput with the new single Buffer API
'use strict';

const common = require('../common.js');
const PORT = common.PORT;

// `num` is the number of send requests to queue up each time.
// Keep it reasonably high (>10) otherwise you're benchmarking the speed of
// event loop cycles more than anything else.
var bench = common.createBenchmark(main, {
len: [1, 64, 256, 1024],
num: [100],
type: ['send', 'recv'],
dur: [5]
});

var dur;
var len;
var num;
var type;
var chunk;
var encoding;

function main(conf) {
dur = +conf.dur;
len = +conf.len;
num = +conf.num;
type = conf.type;
chunk = new Buffer(len);
server();
}

var dgram = require('dgram');

function server() {
var sent = 0;
var received = 0;
var socket = dgram.createSocket('udp4');

function onsend() {
if (sent++ % num == 0)
for (var i = 0; i < num; i++)
socket.send(chunk, PORT, '127.0.0.1', onsend);
}

socket.on('listening', function() {
bench.start();
onsend();

setTimeout(function() {
var bytes = (type === 'send' ? sent : received) * chunk.length;
var gbits = (bytes * 8) / (1024 * 1024 * 1024);
bench.end(gbits);
}, dur * 1000);
});

socket.on('message', function(buf, rinfo) {
received++;
});

socket.bind(PORT);
}
26 changes: 23 additions & 3 deletions doc/api/dgram.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,10 @@ never have reason to call this.
If `multicastInterface` is not specified, the operating system will attempt to
drop membership on all valid interfaces.

### socket.send(buf, offset, length, port, address[, callback])
### socket.send(buf, [offset, length,] port, address[, callback])

* `buf` Buffer object or string. Message to be sent
* `buf` Buffer object, string, or an array of either. Message to be
sent.
* `offset` Integer. Offset in the buffer where the message starts.
* `length` Integer. Number of bytes in the message.
* `port` Integer. Destination port.
Expand Down Expand Up @@ -224,17 +225,36 @@ The only way to know for sure that the datagram has been sent is by using a
passed as the first argument to the `callback`. If a `callback` is not given,
the error is emitted as an `'error'` event on the `socket` object.

Offset and length are optional, but if you specify one you would need to
specify the other. Also, they are supported only when the first
argument is a `Buffer`.

Example of sending a UDP packet to a random port on `localhost`;

```js
const dgram = require('dgram');
const message = new Buffer('Some bytes');
const client = dgram.createSocket('udp4');
client.send(message, 0, message.length, 41234, 'localhost', (err) => {
client.send(message, 41234, 'localhost', (err) => {
client.close();
});
```

Example of sending a UDP packet composed of multiple buffers to a random port on `localhost`;

```js
const dgram = require('dgram');
const buf1 = new Buffer('Some ');
const buf2 = new Buffer('bytes');
const client = dgram.createSocket('udp4');
client.send([buf1, buf2], 41234, 'localhost', (err) => {
client.close();
});
```

Sending multiple buffers might be faster or slower depending on your
application and operating system: benchmark it. Usually it is faster.

**A Note about UDP datagram size**

The maximum size of an `IPv4/v6` datagram depends on the `MTU`
Expand Down
Loading