diff --git a/README.md b/README.md index e1b31f6ae..c52efd72e 100644 --- a/README.md +++ b/README.md @@ -812,7 +812,7 @@ default in Linux can be anywhere from 20-120 seconds][linux-timeout]). --- -- `time` - If `true`, the request-response cycle (including all redirects) is timed at millisecond resolution, and the result provided on the response's `elapsedTime` property. The `responseStartTime` property is also available to indicate the timestamp when the response begins. In addition, there is a `.timings` object available with the following properties: +- `time` - If `true`, the request-response cycle (including all redirects) is timed at millisecond resolution, and the result provided on the response's `elapsedTime` property. The `responseStartTime` property is also available to indicate the timestamp when the response begins. In addition, there is a `.timings` object available with the following properties: - `start`: Timestamp when `request()` was initialized - `socket` Timestamp when the [`http`](https://nodejs.org/api/http.html#http_event_socket) module's `socket` event fires. This happens when the socket is assigned to the request (after DNS has been resolved). - `connect`: Timestamp when the [`http`](https://nodejs.org/api/http.html#http_event_connect) module's `connect` event fires. This happens when the server acknowledges the TCP connection. @@ -820,7 +820,8 @@ default in Linux can be anywhere from 20-120 seconds][linux-timeout]). - `end`: Timestamp when the last bytes of the response are received. - `dns`: Duration of DNS lookup (`timings.socket` - `timings.start`) - `tcp`: Duration of TCP connection (`timings.connect` - `timings.socket`) - - `download`: Duration HTTP fetch (`timings.end` - `timings.response`) + - `firstByte`: Duration of HTTP server response (`timings.response` - `timings.connect`) + - `download`: Duration of HTTP download (`timings.end` - `timings.response`) - `total`: Duration entire HTTP round-trip (`timings.end` - `timings.start`) - `har` - A [HAR 1.2 Request Object](http://www.softwareishard.com/blog/har-12-spec/#request), will be processed from HAR format into options overwriting matching values *(see the [HAR 1.2 section](#support-for-har-1.2) for details)* diff --git a/package.json b/package.json index c47bcd217..2645565c5 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "mime-types": "~2.1.7", "node-uuid": "~1.4.7", "oauth-sign": "~0.8.1", - "performance-now": "^0.2.0", "qs": "~6.3.0", "stringstream": "~0.0.4", "tough-cookie": "~2.3.0", diff --git a/request.js b/request.js index 39d2b37fd..1ea024119 100644 --- a/request.js +++ b/request.js @@ -28,7 +28,6 @@ var http = require('http') , Multipart = require('./lib/multipart').Multipart , Redirect = require('./lib/redirect').Redirect , Tunnel = require('./lib/tunnel').Tunnel - , now = require('performance-now') var safeStringify = helpers.safeStringify , isReadStream = helpers.isReadStream @@ -37,6 +36,7 @@ var safeStringify = helpers.safeStringify , copy = helpers.copy , version = helpers.version , globalCookieJar = cookies.jar() + , hrTimeStart var globalPool = {} @@ -92,6 +92,28 @@ function responseToJSON() { } } +function getHrTime() { + if (typeof process === 'undefined' || !process.hrtime) { + return 0 + } + + var hr = process.hrtime() + // convert to nanoseconds + return hr[0] * 1e9 + hr[1] +} + +hrTimeStart = getHrTime() + +function getTimeFromStart() { + // in the browser, use performance.now() + if (typeof performance !== 'undefined' && performance.now) { + return performance.now() + } + + // in nodejs, use process.hrtime() (converting back to milliseconds) + return (getHrTime() - hrTimeStart) / 1e6 +} + function Request (options) { // if given the method property in options, set property explicitMethod to true @@ -715,7 +737,7 @@ Request.prototype.start = function () { var self = this if (self.timing) { - var startTime = now() + var startTime = getTimeFromStart() } if (self._aborted) { @@ -775,9 +797,9 @@ Request.prototype.start = function () { }) self.req.on('socket', function(socket) { if (self.timing) { - self.timings.socket = now() + self.timings.socket = getTimeFromStart() socket.on('connect', function() { - self.timings.connect = now() + self.timings.connect = getTimeFromStart() }) } @@ -864,13 +886,13 @@ Request.prototype.onRequestResponse = function (response) { var self = this if (self.timing) { - self.timings.response = now() + self.timings.response = getTimeFromStart() } debug('onRequestResponse', self.uri.href, response.statusCode, response.headers) response.on('end', function() { if (self.timing) { - self.timings.end = now() + self.timings.end = getTimeFromStart() self.timings.dns = self.timings.socket - self.timings.start self.timings.tcp = self.timings.connect - self.timings.socket diff --git a/tests/test-timing.js b/tests/test-timing.js index 0e9a7cdf9..6cbed5f1b 100644 --- a/tests/test-timing.js +++ b/tests/test-timing.js @@ -40,7 +40,7 @@ tape('non-redirected request is timed', function(t) { t.equal((res.timings.response >= res.timings.connect), true) t.equal((res.timings.end >= res.timings.response), true) t.equal((res.timings.dns >= 0), true) - t.equal((res.timings.tcp > 0), true) + t.equal((res.timings.tcp >= 0), true) t.equal((res.timings.firstByte > 0), true) t.equal((res.timings.download > 0), true) t.equal((res.timings.total > 0), true)