| |
| /*! |
| * Connect - profiler |
| * Copyright(c) 2011 TJ Holowaychuk |
| * MIT Licensed |
| */ |
| |
| /** |
| * Profile the duration of a request. |
| * |
| * Typically this middleware should be utilized |
| * _above_ all others, as it proxies the `res.end()` |
| * method, being first allows it to encapsulate all |
| * other middleware. |
| * |
| * Example Output: |
| * |
| * GET / |
| * response time 2ms |
| * memory rss 52.00kb |
| * memory vsize 2.07mb |
| * heap before 3.76mb / 8.15mb |
| * heap after 3.80mb / 8.15mb |
| * |
| * @api public |
| */ |
| |
| module.exports = function profiler(){ |
| return function(req, res, next){ |
| var end = res.end |
| , start = snapshot(); |
| |
| // state snapshot |
| function snapshot() { |
| return { |
| mem: process.memoryUsage() |
| , time: new Date |
| }; |
| } |
| |
| // proxy res.end() |
| res.end = function(data, encoding){ |
| res.end = end; |
| res.end(data, encoding); |
| compare(req, start, snapshot()) |
| }; |
| |
| next(); |
| } |
| }; |
| |
| /** |
| * Compare `start` / `end` snapshots. |
| * |
| * @param {IncomingRequest} req |
| * @param {Object} start |
| * @param {Object} end |
| * @api private |
| */ |
| |
| function compare(req, start, end) { |
| console.log(); |
| row(req.method, req.url); |
| row('response time:', (end.time - start.time) + 'ms'); |
| row('memory rss:', formatBytes(end.mem.rss - start.mem.rss)); |
| row('memory vsize:', formatBytes(end.mem.vsize - start.mem.vsize)); |
| row('heap before:', formatBytes(start.mem.heapUsed) + ' / ' + formatBytes(start.mem.heapTotal)); |
| row('heap after:', formatBytes(end.mem.heapUsed) + ' / ' + formatBytes(end.mem.heapTotal)); |
| console.log(); |
| } |
| |
| /** |
| * Row helper |
| * |
| * @param {String} key |
| * @param {String} val |
| * @api private |
| */ |
| |
| function row(key, val) { |
| console.log(' \033[90m%s\033[0m \033[36m%s\033[0m', key, val); |
| } |
| |
| /** |
| * Format byte-size. |
| * |
| * @param {Number} bytes |
| * @return {String} |
| * @api private |
| */ |
| |
| function formatBytes(bytes) { |
| var kb = 1024 |
| , mb = 1024 * kb |
| , gb = 1024 * mb; |
| if (bytes < kb) return bytes + 'b'; |
| if (bytes < mb) return (bytes / kb).toFixed(2) + 'kb'; |
| if (bytes < gb) return (bytes / mb).toFixed(2) + 'mb'; |
| return (bytes / gb).toFixed(2) + 'gb'; |
| }; |