Skip to content

Instantly share code, notes, and snippets.

@ginpei
Last active October 6, 2022 21:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ginpei/1aa6329c6a747f6b9dab7223f0ba2ebe to your computer and use it in GitHub Desktop.
Save ginpei/1aa6329c6a747f6b9dab7223f0ba2ebe to your computer and use it in GitHub Desktop.
Measure Express.js middleware runtime performance
const app = express();
const _use = app.use;
let numUseCalls = 0;
app.use = function(...args) {
const fn = args[args.length - 1];
// except `express.static()`
if (fn && fn.name === 'serveStatic') {
_use.apply(this, args);
return;
}
const useCallIndex = numUseCalls++;
const fnName = fn.name || '(anonymous)';
const { stack } = new Error();
const lines = stack.split('\n');
const callerLine = lines[2];
const fnPath = callerLine.trim().slice('at '.length);
const paramTypes = args.map((v) => typeof v);
console.log(`use#${useCallIndex} ${fnName} ${fnPath}`, paramTypes);
const wrappedArgs = [...args];
wrappedArgs.pop();
if (typeof fn !== 'function') {
throw new Error();
}
const measure = async (...mArgs) => {
console.time(`use#${useCallIndex} ${fnName} ${fnPath}`);
const result = await fn(...mArgs);
console.timeEnd(`use#${useCallIndex} ${fnName} ${fnPath}`);
return result;
};
wrappedArgs.push(measure);
_use.apply(this, wrappedArgs);
};
use#3 (anonymous) /path/to/my/server.js:216:6: 2.002ms
use#2 compression /path/to/my/server.js:182:6: 2.136ms
use#1 methodOverride /path/to/my/server.js:180:6: 2.312ms
use#0 cookieParser /path/to/my/server.js:177:6: 2.541ms
use#4 bound initialize /path/to/my/server.js:257:6: 1.697ms
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment