0

I'm relatively new to JS, and was trying to benchmark some code (to study performance of various algorithms) so I could just see how long things took when running on my terminal. I originally had:

function benchmark(callback, name = `${callback+""}`) { // Convert callback to literal string if no name provided
  console.log(`${name}`);
  console.time("time");
  console.log(`\t${callback}`);
  console.timeEnd("time");
  console.log('\n');
}

However, I am not receiving the time it takes to run the function. For example, my output states it takes longer to find the 6th fibonacci number than the 50th.

Example 1:

function fib(n) {
  if (n === 1 || n === 2) return 1;
  return fib(n - 1) + fib(n - 2);
}

When I run:

benchmark(fib(6), "fib(6) Rep 1");    // 0.5449770092964172ms
benchmark(fib(50), "fib(50) Rep 1"); //  0.004218995571136475ms

It takes longer for fib(50) to finish, but the measured time is shorter!

Modified benchmark via performance.now() also doesn't work

I run into the same issue above if I use performance.now().

const {performance} = require('perf_hooks');
function benchmark(callback, name = `${callback+""}`) {
  let t0 = performance.now();
  let result = callback;
  let t1 = performance.now();
  console.log(`\t${result}`);
  console.log(`time: ${t1 - t0}ms`);
  console.log('\n');
};

I suspect the timers are stopping randomly or before the call is over. Should I convert the callback to a promise, and use either .then or await? Or am I missing something more fundamental about JS (like the event loop or call stack)?

I've gone through:

A Duv
  • 364
  • 1
  • 15
  • 2
    I am unable to post an answer to this question for some reason. The problem is that a line like `benchmark(fib(6), "fib(6) Rep 1");` **evaluates fib(6) first** and then passes the return value into `benchmark()`. So your "callback" is actually just a number, not a function - your fibonacci sequence is already computed before you start timing. You should pass it a callback that runs the fibonacci sequence like this: `benchmark(() => fib(6), "fib(6) Rep 1");` and then make sure to *call* the callback with parentheses: `console.log(callback())` – Klaycon Jan 30 '20 at 21:09
  • That was silly of me; thank you for catching it. I posted your suggestion with example code below so others can see it more readily (and credited you of course). Once you can post an answer I'll select yours as the answer! – A Duv Jan 30 '20 at 21:39
  • No need, the answer you posted is the answer to the question. Feel free to just accept that one, I already lost the answer I typed out previously anyway. Glad it helped you solve the problem though. – Klaycon Jan 30 '20 at 21:55
  • True. It won't let me select my answer as the answer I chose in the meantime, which is why I offered. – A Duv Jan 30 '20 at 22:52

1 Answers1

3

Klaycon solved this for me in the comment above but can't post an answer for some reason. I was passing in a number (and not a callback); I was evaluating the callback BEFORE the timers.

To resolve my issue, I first need to pass an actual callback into my benchmark() function:

  benchmark( () => fib(6), "fib(6) Rep 1");

and then I need to invoke my callback in my benchmark function itself:

function benchmark(callback, name = `${callback + ""}`) {
  console.log(`${name}`);
  console.time("time");
  console.log(`\t${callback()}`);          // ##### CHANGE HERE ######
  console.timeEnd("time");
  console.log('\n');
}
A Duv
  • 364
  • 1
  • 15