rink.attendant.6
rink.attendant.6

Reputation: 46208

Timing/performance metrics of npm scripts

Is there a way to measure the performance of an npm scripts similar to the way time-grunt works?

I am moving some of my critical build tasks to use npm instead of Grunt as writing my own build script is more flexible than using some of the Grunt plugins like grunt-browserify for example.

I have tried using console.time() but it finishes before the script is done, I assume because the methods are asynchronous. I also tried running the npm script as a Grunt task like this:

grunt.registerTask('collectify', function () {
    grunt.util.spawn({
        cmd: 'npm',
        args: ['run', 'collectify:app']
    });
});

But the output is different than if I run npm run collectify:app from the command line, perhaps because of pwd issues.

Coloured bars would be nice but at the very least I'd like to see the time in numbers.

Upvotes: 3

Views: 2201

Answers (3)

Justin Grant
Justin Grant

Reputation: 46663

I wrote a simple JavaScript program that is similar to the functionality of the UNIX/Linux/MacOS time command, but it should work cross-platform.

  1. Save the code below into ./time.mjs.
  2. chmod +x ./time.mjs to let it be executed on non-Windows OSes.
  3. Here's an example of how I use it in package.json:
    "lint": "./time.mjs eslint . --cache --max-warnings 0",
#!/usr/bin/env node
/* eslint-disable no-console */

import { spawn } from 'child_process'
import { performance } from 'perf_hooks'
import os from 'os'

// Helper function to format time
const formatTime = timeInMs => (timeInMs / 1000).toFixed(2) + 's'

// Ensure a command is provided
if (process.argv.length < 3) {
  console.error('Usage: timing.mjs <command> [args...]')
  process.exit(1)
}

const command = process.argv[2]
const args = process.argv.slice(3)

const startTime = performance.now()

const child = spawn(command, args, { stdio: 'inherit', shell: os.platform() === 'win32' })

child.on('exit', code => {
  const elapsedTime = performance.now() - startTime

  console.log(`\nCommand executed: ${command} ${args.join(' ')}`)
  console.log(`Elapsed time: ${formatTime(elapsedTime)}`)

  process.exit(code)
})

child.on('error', err => {
  console.error(`Failed to start command: ${err.message}`)
  process.exit(1)
})

Upvotes: 0

mass
mass

Reputation: 41

Have you tried prepending the time command before your npm run command ?

So if your command is:

npm run collectify:app

It becomes:

time npm run collectify:app

And it'll output 3 lines e.g.

real    0m11.580s
user    0m7.400s
sys     0m1.304s

Let me know if it helps!

Upvotes: 4

Jason Palmer JSONP
Jason Palmer JSONP

Reputation: 85

Your best option is likely pre[foo] and post[foo] scripts.

So if I have a NPM script called "foobar" then I can create a script called "preboofar" and "postfoobar" and they will be executed automatically before and after "foobar" is executed.

So in "pre" you can touch a file with a timestamp and in "post" you can read that file and calculate the difference.

Upvotes: 1

Related Questions