| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 902776e commit b71a810
8 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -531,6 +531,30 @@ When `performanceEntry.type` is equal to `'function'`, the | |||
| 531 | 531 | `performanceEntry.detail` property will be an {Array} listing | |
| 532 | 532 | the input arguments to the timed function. | |
| 533 | 533 | ||
| 534 | + ### Net ('net') Details | ||
| 535 | + | ||
| 536 | + When `performanceEntry.type` is equal to `'net'`, the | ||
| 537 | + `performanceEntry.detail` property will be an {Object} containing | ||
| 538 | + additional information. | ||
| 539 | + | ||
| 540 | + If `performanceEntry.name` is equal to `connect`, the `detail` | ||
| 541 | + will contain the following properties: `host`, `port`. | ||
| 542 | + | ||
| 543 | + ### DNS ('dns') Details | ||
| 544 | + | ||
| 545 | + When `performanceEntry.type` is equal to `'dns'`, the | ||
| 546 | + `performanceEntry.detail` property will be an {Object} containing | ||
| 547 | + additional information. | ||
| 548 | + | ||
| 549 | + If `performanceEntry.name` is equal to `lookup`, the `detail` | ||
| 550 | + will contain the following properties: `hostname`, `family`, `hints`, `verbatim`. | ||
| 551 | + | ||
| 552 | + If `performanceEntry.name` is equal to `lookupService`, the `detail` will | ||
| 553 | + contain the following properties: `host`, `port`. | ||
| 554 | + | ||
| 555 | + If `performanceEntry.name` is equal to `queryxxx` or `getHostByAddr`, the `detail` will | ||
| 556 | + contain the following properties: `host`, `ttl`. | ||
| 557 | + | ||
| 534 | 558 | ## Class: `PerformanceNodeTiming` | |
| 535 | 559 | ||
| 536 | 560 | <!-- YAML | |
@@ -1284,6 +1308,42 @@ http.createServer((req, res) => { | |||
| 1284 | 1308 | }); | |
| 1285 | 1309 | ``` | |
| 1286 | 1310 | ||
| 1311 | + ### Measuring how long the `net.connect` (only for TCP) takes when the connection is successful | ||
| 1312 | + | ||
| 1313 | + ```js | ||
| 1314 | + 'use strict'; | ||
| 1315 | + const { PerformanceObserver } = require('perf_hooks'); | ||
| 1316 | + const net = require('net'); | ||
| 1317 | + const obs = new PerformanceObserver((items) => { | ||
| 1318 | + items.getEntries().forEach((item) => { | ||
| 1319 | + console.log(item); | ||
| 1320 | + }); | ||
| 1321 | + }); | ||
| 1322 | + obs.observe({ entryTypes: ['net'] }); | ||
| 1323 | + const PORT = 8080; | ||
| 1324 | + net.createServer((socket) => { | ||
| 1325 | + socket.destroy(); | ||
| 1326 | + }).listen(PORT, () => { | ||
| 1327 | + net.connect(PORT); | ||
| 1328 | + }); | ||
| 1329 | + ``` | ||
| 1330 | + | ||
| 1331 | + ### Measuring how long the DNS takes when the request is successful | ||
| 1332 | + | ||
| 1333 | + ```js | ||
| 1334 | + 'use strict'; | ||
| 1335 | + const { PerformanceObserver } = require('perf_hooks'); | ||
| 1336 | + const dns = require('dns'); | ||
| 1337 | + const obs = new PerformanceObserver((items) => { | ||
| 1338 | + items.getEntries().forEach((item) => { | ||
| 1339 | + console.log(item); | ||
| 1340 | + }); | ||
| 1341 | + }); | ||
| 1342 | + obs.observe({ entryTypes: ['dns'] }); | ||
| 1343 | + dns.lookup('localhost', () => {}); | ||
| 1344 | + dns.promises.resolve('localhost'); | ||
| 1345 | + ``` | ||
| 1346 | + | ||
| 1287 | 1347 | [Async Hooks]: async_hooks.md | |
| 1288 | 1348 | [High Resolution Time]: https://www.w3.org/TR/hr-time-2 | |
| 1289 | 1349 | [Performance Timeline]: https://w3c.github.io/performance-timeline/ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -27,6 +27,7 @@ const { | |||
| 27 | 27 | ObjectDefineProperties, | |
| 28 | 28 | ObjectDefineProperty, | |
| 29 | 29 | ReflectApply, | |
| 30 | + Symbol, | ||
| 30 | 31 | } = primordials; | |
| 31 | 32 | ||
| 32 | 33 | const cares = internalBinding('cares_wrap'); | |
@@ -63,6 +64,15 @@ const { | |||
| 63 | 64 | QueryReqWrap, | |
| 64 | 65 | } = cares; | |
| 65 | 66 | ||
| 67 | + const kPerfHooksDnsLookupContext = Symbol('kPerfHooksDnsLookupContext'); | ||
| 68 | + const kPerfHooksDnsLookupServiceContext = Symbol('kPerfHooksDnsLookupServiceContext'); | ||
| 69 | + const kPerfHooksDnsLookupResolveContext = Symbol('kPerfHooksDnsLookupResolveContext'); | ||
| 70 | + | ||
| 71 | + const { | ||
| 72 | + startPerf, | ||
| 73 | + stopPerf, | ||
| 74 | + } = require('internal/perf/observe'); | ||
| 75 | + | ||
| 66 | 76 | const dnsException = errors.dnsException; | |
| 67 | 77 | ||
| 68 | 78 | let promises = null; // Lazy loaded | |
@@ -72,6 +82,7 @@ function onlookup(err, addresses) { | |||
| 72 | 82 | return this.callback(dnsException(err, 'getaddrinfo', this.hostname)); | |
| 73 | 83 | } | |
| 74 | 84 | this.callback(null, addresses[0], this.family || isIP(addresses[0])); | |
| 85 | + stopPerf(this, kPerfHooksDnsLookupContext); | ||
| 75 | 86 | } | |
| 76 | 87 | ||
| 77 | 88 | ||
@@ -90,6 +101,7 @@ function onlookupall(err, addresses) { | |||
| 90 | 101 | } | |
| 91 | 102 | ||
| 92 | 103 | this.callback(null, addresses); | |
| 104 | + stopPerf(this, kPerfHooksDnsLookupContext); | ||
| 93 | 105 | } | |
| 94 | 106 | ||
| 95 | 107 | ||
@@ -176,6 +188,13 @@ function lookup(hostname, options, callback) { | |||
| 176 | 188 | process.nextTick(callback, dnsException(err, 'getaddrinfo', hostname)); | |
| 177 | 189 | return {}; | |
| 178 | 190 | } | |
| 191 | + const detail = { | ||
| 192 | + hostname, | ||
| 193 | + family, | ||
| 194 | + hints, | ||
| 195 | + verbatim, | ||
| 196 | + }; | ||
| 197 | + startPerf(req, kPerfHooksDnsLookupContext, { type: 'dns', name: 'lookup', detail }); | ||
| 179 | 198 | return req; | |
| 180 | 199 | } | |
| 181 | 200 | ||
@@ -188,6 +207,7 @@ function onlookupservice(err, hostname, service) { | |||
| 188 | 207 | return this.callback(dnsException(err, 'getnameinfo', this.hostname)); | |
| 189 | 208 | ||
| 190 | 209 | this.callback(null, hostname, service); | |
| 210 | + stopPerf(this, kPerfHooksDnsLookupServiceContext); | ||
| 191 | 211 | } | |
| 192 | 212 | ||
| 193 | 213 | ||
@@ -212,6 +232,14 @@ function lookupService(address, port, callback) { | |||
| 212 | 232 | ||
| 213 | 233 | const err = cares.getnameinfo(req, address, port); | |
| 214 | 234 | if (err) throw dnsException(err, 'getnameinfo', address); | |
| 235 | + startPerf(req, kPerfHooksDnsLookupServiceContext, { | ||
| 236 | + type: 'dns', | ||
| 237 | + name: 'lookupService', | ||
| 238 | + detail: { | ||
| 239 | + host: address, | ||
| 240 | + port | ||
| 241 | + } | ||
| 242 | + }); | ||
| 215 | 243 | return req; | |
| 216 | 244 | } | |
| 217 | 245 | ||
@@ -226,8 +254,10 @@ function onresolve(err, result, ttls) { | |||
| 226 | 254 | ||
| 227 | 255 | if (err) | |
| 228 | 256 | this.callback(dnsException(err, this.bindingName, this.hostname)); | |
| 229 | - else | ||
| 257 | + else { | ||
| 230 | 258 | this.callback(null, result); | |
| 259 | + stopPerf(this, kPerfHooksDnsLookupResolveContext); | ||
| 260 | + } | ||
| 231 | 261 | } | |
| 232 | 262 | ||
| 233 | 263 | function resolver(bindingName) { | |
@@ -249,6 +279,14 @@ function resolver(bindingName) { | |||
| 249 | 279 | req.ttl = !!(options && options.ttl); | |
| 250 | 280 | const err = this._handle[bindingName](req, toASCII(name)); | |
| 251 | 281 | if (err) throw dnsException(err, bindingName, name); | |
| 282 | + startPerf(req, kPerfHooksDnsLookupResolveContext, { | ||
| 283 | + type: 'dns', | ||
| 284 | + name: bindingName, | ||
| 285 | + detail: { | ||
| 286 | + host: name, | ||
| 287 | + ttl: req.ttl | ||
| 288 | + } | ||
| 289 | + }); | ||
| 252 | 290 | return req; | |
| 253 | 291 | } | |
| 254 | 292 | ObjectDefineProperty(query, 'name', { value: bindingName }); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,6 +5,7 @@ const { | |||
| 5 | 5 | ObjectDefineProperty, | |
| 6 | 6 | Promise, | |
| 7 | 7 | ReflectApply, | |
| 8 | + Symbol, | ||
| 8 | 9 | } = primordials; | |
| 9 | 10 | ||
| 10 | 11 | const { | |
@@ -38,6 +39,15 @@ const { | |||
| 38 | 39 | validateOneOf, | |
| 39 | 40 | } = require('internal/validators'); | |
| 40 | 41 | ||
| 42 | + const kPerfHooksDnsLookupContext = Symbol('kPerfHooksDnsLookupContext'); | ||
| 43 | + const kPerfHooksDnsLookupServiceContext = Symbol('kPerfHooksDnsLookupServiceContext'); | ||
| 44 | + const kPerfHooksDnsLookupResolveContext = Symbol('kPerfHooksDnsLookupResolveContext'); | ||
| 45 | + | ||
| 46 | + const { | ||
| 47 | + startPerf, | ||
| 48 | + stopPerf, | ||
| 49 | + } = require('internal/perf/observe'); | ||
| 50 | + | ||
| 41 | 51 | function onlookup(err, addresses) { | |
| 42 | 52 | if (err) { | |
| 43 | 53 | this.reject(dnsException(err, 'getaddrinfo', this.hostname)); | |
@@ -46,6 +56,7 @@ function onlookup(err, addresses) { | |||
| 46 | 56 | ||
| 47 | 57 | const family = this.family || isIP(addresses[0]); | |
| 48 | 58 | this.resolve({ address: addresses[0], family }); | |
| 59 | + stopPerf(this, kPerfHooksDnsLookupContext); | ||
| 49 | 60 | } | |
| 50 | 61 | ||
| 51 | 62 | function onlookupall(err, addresses) { | |
@@ -66,6 +77,7 @@ function onlookupall(err, addresses) { | |||
| 66 | 77 | } | |
| 67 | 78 | ||
| 68 | 79 | this.resolve(addresses); | |
| 80 | + stopPerf(this, kPerfHooksDnsLookupContext); | ||
| 69 | 81 | } | |
| 70 | 82 | ||
| 71 | 83 | function createLookupPromise(family, hostname, all, hints, verbatim) { | |
@@ -96,6 +108,14 @@ function createLookupPromise(family, hostname, all, hints, verbatim) { | |||
| 96 | 108 | ||
| 97 | 109 | if (err) { | |
| 98 | 110 | reject(dnsException(err, 'getaddrinfo', hostname)); | |
| 111 | + } else { | ||
| 112 | + const detail = { | ||
| 113 | + hostname, | ||
| 114 | + family, | ||
| 115 | + hints, | ||
| 116 | + verbatim, | ||
| 117 | + }; | ||
| 118 | + startPerf(req, kPerfHooksDnsLookupContext, { type: 'dns', name: 'lookup', detail }); | ||
| 99 | 119 | } | |
| 100 | 120 | }); | |
| 101 | 121 | } | |
@@ -151,6 +171,7 @@ function onlookupservice(err, hostname, service) { | |||
| 151 | 171 | } | |
| 152 | 172 | ||
| 153 | 173 | this.resolve({ hostname, service }); | |
| 174 | + stopPerf(this, kPerfHooksDnsLookupServiceContext); | ||
| 154 | 175 | } | |
| 155 | 176 | ||
| 156 | 177 | function createLookupServicePromise(hostname, port) { | |
@@ -167,6 +188,15 @@ function createLookupServicePromise(hostname, port) { | |||
| 167 | 188 | ||
| 168 | 189 | if (err) | |
| 169 | 190 | reject(dnsException(err, 'getnameinfo', hostname)); | |
| 191 | + else | ||
| 192 | + startPerf(req, kPerfHooksDnsLookupServiceContext, { | ||
| 193 | + type: 'dns', | ||
| 194 | + name: 'lookupService', | ||
| 195 | + detail: { | ||
| 196 | + host: hostname, | ||
| 197 | + port | ||
| 198 | + } | ||
| 199 | + }); | ||
| 170 | 200 | }); | |
| 171 | 201 | } | |
| 172 | 202 | ||
@@ -194,6 +224,7 @@ function onresolve(err, result, ttls) { | |||
| 194 | 224 | result, (address, index) => ({ address, ttl: ttls[index] })); | |
| 195 | 225 | ||
| 196 | 226 | this.resolve(result); | |
| 227 | + stopPerf(this, kPerfHooksDnsLookupResolveContext); | ||
| 197 | 228 | } | |
| 198 | 229 | ||
| 199 | 230 | function createResolverPromise(resolver, bindingName, hostname, ttl) { | |
@@ -211,6 +242,16 @@ function createResolverPromise(resolver, bindingName, hostname, ttl) { | |||
| 211 | 242 | ||
| 212 | 243 | if (err) | |
| 213 | 244 | reject(dnsException(err, bindingName, hostname)); | |
| 245 | + else { | ||
| 246 | + startPerf(req, kPerfHooksDnsLookupResolveContext, { | ||
| 247 | + type: 'dns', | ||
| 248 | + name: bindingName, | ||
| 249 | + detail: { | ||
| 250 | + host: hostname, | ||
| 251 | + ttl | ||
| 252 | + } | ||
| 253 | + }); | ||
| 254 | + } | ||
| 214 | 255 | }); | |
| 215 | 256 | } | |
| 216 | 257 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -24,6 +24,8 @@ const { | |||
| 24 | 24 | NODE_PERFORMANCE_ENTRY_TYPE_GC, | |
| 25 | 25 | NODE_PERFORMANCE_ENTRY_TYPE_HTTP2, | |
| 26 | 26 | NODE_PERFORMANCE_ENTRY_TYPE_HTTP, | |
| 27 | + NODE_PERFORMANCE_ENTRY_TYPE_NET, | ||
| 28 | + NODE_PERFORMANCE_ENTRY_TYPE_DNS, | ||
| 27 | 29 | }, | |
| 28 | 30 | installGarbageCollectionTracking, | |
| 29 | 31 | observerCounts, | |
@@ -79,12 +81,14 @@ const kTypeMultiple = 1; | |||
| 79 | 81 | let gcTrackingInstalled = false; | |
| 80 | 82 | ||
| 81 | 83 | const kSupportedEntryTypes = ObjectFreeze([ | |
| 84 | + 'dns', | ||
| 82 | 85 | 'function', | |
| 83 | 86 | 'gc', | |
| 84 | 87 | 'http', | |
| 85 | 88 | 'http2', | |
| 86 | 89 | 'mark', | |
| 87 | 90 | 'measure', | |
| 91 | + 'net', | ||
| 88 | 92 | ]); | |
| 89 | 93 | ||
| 90 | 94 | // Performance timeline entry Buffers | |
@@ -118,6 +122,8 @@ function getObserverType(type) { | |||
| 118 | 122 | case 'gc': return NODE_PERFORMANCE_ENTRY_TYPE_GC; | |
| 119 | 123 | case 'http2': return NODE_PERFORMANCE_ENTRY_TYPE_HTTP2; | |
| 120 | 124 | case 'http': return NODE_PERFORMANCE_ENTRY_TYPE_HTTP; | |
| 125 | + case 'net': return NODE_PERFORMANCE_ENTRY_TYPE_NET; | ||
| 126 | + case 'dns': return NODE_PERFORMANCE_ENTRY_TYPE_DNS; | ||
| 121 | 127 | } | |
| 122 | 128 | } | |
| 123 | 129 | ||
@@ -443,11 +449,39 @@ function hasObserver(type) { | |||
| 443 | 449 | return observerCounts[observerType] > 0; | |
| 444 | 450 | } | |
| 445 | 451 | ||
| 452 | + | ||
| 453 | + function startPerf(target, key, context = {}) { | ||
| 454 | + if (hasObserver(context.type)) { | ||
| 455 | + target[key] = { | ||
| 456 | + ...context, | ||
| 457 | + startTime: process.hrtime(), | ||
| 458 | + }; | ||
| 459 | + } | ||
| 460 | + } | ||
| 461 | + | ||
| 462 | + function stopPerf(target, key, context = {}) { | ||
| 463 | + const ctx = target[key]; | ||
| 464 | + if (ctx && hasObserver(ctx.type)) { | ||
| 465 | + const startTime = ctx.startTime; | ||
| 466 | + const diff = process.hrtime(startTime); | ||
| 467 | + const entry = new InternalPerformanceEntry( | ||
| 468 | + ctx.name, | ||
| 469 | + ctx.type, | ||
| 470 | + startTime[0] * 1000 + startTime[1] / 1e6, | ||
| 471 | + diff[0] * 1000 + diff[1] / 1e6, | ||
| 472 | + { ...ctx.detail, ...context.detail }, | ||
| 473 | + ); | ||
| 474 | + enqueue(entry); | ||
| 475 | + } | ||
| 476 | + } | ||
| 477 | + | ||
| 446 | 478 | module.exports = { | |
| 447 | 479 | PerformanceObserver, | |
| 448 | 480 | PerformanceObserverEntryList, | |
| 449 | 481 | enqueue, | |
| 450 | 482 | hasObserver, | |
| 451 | 483 | clearEntriesFromBuffer, | |
| 452 | 484 | filterBufferMapByNameAndType, | |
| 485 | + startPerf, | ||
| 486 | + stopPerf, | ||
| 453 | 487 | }; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -130,6 +130,12 @@ const isWindows = process.platform === 'win32'; | |||
| 130 | 130 | ||
| 131 | 131 | const noop = () => {}; | |
| 132 | 132 | ||
| 133 | + const kPerfHooksNetConnectContext = Symbol('kPerfHooksNetConnectContext'); | ||
| 134 | + const { | ||
| 135 | + startPerf, | ||
| 136 | + stopPerf, | ||
| 137 | + } = require('internal/perf/observe'); | ||
| 138 | + | ||
| 133 | 139 | function getFlags(ipv6Only) { | |
| 134 | 140 | return ipv6Only === true ? TCPConstants.UV_TCP_IPV6ONLY : 0; | |
| 135 | 141 | } | |
@@ -952,6 +958,8 @@ function internalConnect( | |||
| 952 | 958 | ||
| 953 | 959 | const ex = exceptionWithHostPort(err, 'connect', address, port, details); | |
| 954 | 960 | self.destroy(ex); | |
| 961 | + } else if (addressType === 6 || addressType === 4) { | ||
| 962 | + startPerf(self, kPerfHooksNetConnectContext, { type: 'net', name: 'connect', detail: { host: address, port } }); | ||
| 955 | 963 | } | |
| 956 | 964 | } | |
| 957 | 965 | ||
@@ -1177,7 +1185,7 @@ function afterConnect(status, handle, req, readable, writable) { | |||
| 1177 | 1185 | // this doesn't actually consume any bytes, because len=0. | |
| 1178 | 1186 | if (readable && !self.isPaused()) | |
| 1179 | 1187 | self.read(0); | |
| 1180 | - | ||
| 1188 | + stopPerf(self, kPerfHooksNetConnectContext); | ||
| 1181 | 1189 | } else { | |
| 1182 | 1190 | self.connecting = false; | |
| 1183 | 1191 | let details; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -34,7 +34,9 @@ extern uint64_t performance_v8_start; | |||
| 34 | 34 | #define NODE_PERFORMANCE_ENTRY_TYPES(V) \ | |
| 35 | 35 | V(GC, "gc") \ | |
| 36 | 36 | V(HTTP, "http") \ | |
| 37 | - V(HTTP2, "http2") | ||
| 37 | + V(HTTP2, "http2") \ | ||
| 38 | + V(NET, "net") \ | ||
| 39 | + V(DNS, "dns") | ||
| 38 | 40 | ||
| 39 | 41 | enum PerformanceMilestone { | |
| 40 | 42 | #define V(name, _) NODE_PERFORMANCE_MILESTONE_##name, | |
| Back | FazBrowse Home | New Git URL |
0 commit comments