Skip to content

Commit 007a033

Browse files
mscdexjasnell
authored andcommitted
dns: improve callback performance
It appears that either c-ares no longer calls callbacks synchronously or we have since explicitly taken care of the scenarios in which c-ares would call callbacks synchronously (e.g. resolving an IP address or an empty hostname). Therefore we no longer need to have machinery in place to handle possible synchronous callback invocation. This improves performance significantly. PR-URL: #13261 Reviewed-By: Roman Reiss <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent dccd1d2 commit 007a033

File tree

2 files changed

+44
-43
lines changed

2 files changed

+44
-43
lines changed

benchmark/dns/lookup.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use strict';
2+
3+
const common = require('../common.js');
4+
const lookup = require('dns').lookup;
5+
6+
const bench = common.createBenchmark(main, {
7+
name: ['', '127.0.0.1', '::1'],
8+
all: [true, false],
9+
n: [5e6]
10+
});
11+
12+
function main(conf) {
13+
const name = conf.name;
14+
const n = +conf.n;
15+
const all = !!conf.all;
16+
var i = 0;
17+
18+
if (all) {
19+
const opts = { all: true };
20+
bench.start();
21+
(function cb(err, results) {
22+
if (i++ === n) {
23+
bench.end(n);
24+
return;
25+
}
26+
lookup(name, opts, cb);
27+
})();
28+
} else {
29+
bench.start();
30+
(function cb(err, result) {
31+
if (i++ === n) {
32+
bench.end(n);
33+
return;
34+
}
35+
lookup(name, cb);
36+
})();
37+
}
38+
}

lib/dns.js

+6-43
Original file line numberDiff line numberDiff line change
@@ -61,35 +61,6 @@ function errnoException(err, syscall, hostname) {
6161
}
6262

6363

64-
// c-ares invokes a callback either synchronously or asynchronously,
65-
// but the dns API should always invoke a callback asynchronously.
66-
//
67-
// This function makes sure that the callback is invoked asynchronously.
68-
// It returns a function that invokes the callback within nextTick().
69-
//
70-
// To avoid invoking unnecessary nextTick(), `immediately` property of
71-
// returned function should be set to true after c-ares returned.
72-
//
73-
// Usage:
74-
//
75-
// function someAPI(callback) {
76-
// callback = makeAsync(callback);
77-
// channel.someAPI(..., callback);
78-
// callback.immediately = true;
79-
// }
80-
function makeAsync(callback) {
81-
return function asyncCallback(...args) {
82-
if (asyncCallback.immediately) {
83-
// The API already returned, we can invoke the callback immediately.
84-
callback.apply(null, args);
85-
} else {
86-
args.unshift(callback);
87-
process.nextTick.apply(null, args);
88-
}
89-
};
90-
}
91-
92-
9364
function onlookup(err, addresses) {
9465
if (err) {
9566
return this.callback(errnoException(err, 'getaddrinfo', this.hostname));
@@ -153,23 +124,22 @@ function lookup(hostname, options, callback) {
153124
if (family !== 0 && family !== 4 && family !== 6)
154125
throw new TypeError('Invalid argument: family must be 4 or 6');
155126

156-
callback = makeAsync(callback);
157-
158127
if (!hostname) {
159128
if (all) {
160-
callback(null, []);
129+
process.nextTick(callback, null, []);
161130
} else {
162-
callback(null, null, family === 6 ? 6 : 4);
131+
process.nextTick(callback, null, null, family === 6 ? 6 : 4);
163132
}
164133
return {};
165134
}
166135

167136
var matchedFamily = isIP(hostname);
168137
if (matchedFamily) {
169138
if (all) {
170-
callback(null, [{address: hostname, family: matchedFamily}]);
139+
process.nextTick(
140+
callback, null, [{address: hostname, family: matchedFamily}]);
171141
} else {
172-
callback(null, hostname, matchedFamily);
142+
process.nextTick(callback, null, hostname, matchedFamily);
173143
}
174144
return {};
175145
}
@@ -182,11 +152,9 @@ function lookup(hostname, options, callback) {
182152

183153
var err = cares.getaddrinfo(req, hostname, family, hints);
184154
if (err) {
185-
callback(errnoException(err, 'getaddrinfo', hostname));
155+
process.nextTick(callback, errnoException(err, 'getaddrinfo', hostname));
186156
return {};
187157
}
188-
189-
callback.immediately = true;
190158
return req;
191159
}
192160

@@ -217,7 +185,6 @@ function lookupService(host, port, callback) {
217185
throw new TypeError('"callback" argument must be a function');
218186

219187
port = +port;
220-
callback = makeAsync(callback);
221188

222189
var req = new GetNameInfoReqWrap();
223190
req.callback = callback;
@@ -227,8 +194,6 @@ function lookupService(host, port, callback) {
227194

228195
var err = cares.getnameinfo(req, host, port);
229196
if (err) throw errnoException(err, 'getnameinfo', host);
230-
231-
callback.immediately = true;
232197
return req;
233198
}
234199

@@ -263,7 +228,6 @@ function resolver(bindingName) {
263228
throw new Error('"callback" argument must be a function');
264229
}
265230

266-
callback = makeAsync(callback);
267231
var req = new QueryReqWrap();
268232
req.bindingName = bindingName;
269233
req.callback = callback;
@@ -272,7 +236,6 @@ function resolver(bindingName) {
272236
req.ttl = !!(options && options.ttl);
273237
var err = binding(req, name);
274238
if (err) throw errnoException(err, bindingName);
275-
callback.immediately = true;
276239
return req;
277240
};
278241
}

0 commit comments

Comments
 (0)