JavaScript・Node.js で実行速度を計測する方法まとめ

ブラウザ JavaScript や Node.js 上で実行速度を計測する方法を改めてまとめる。new Date() の差分で確認する方法は省略。

目次

Sleep 関数もおさらい

JS の世界で Wait・Sleep 相当の処理を行うには setTimeout で遅延させるのを await で待つのが良い。今回、Node.js v16 から使えるようになった timers/promises.setTimeout という関数も試してみた。

// Node.js ではコレで Sleep が使える
const wait = require('timers/promises').setTimeout;

// ブラウザでも Node.js でも使えるポリフィル的な Sleep
const wait = ms => new Promise(r => setTimeout(r, ms));

// どちらの関数も次のように使える
(async () => {
  console.log('Start');
  await wait(1000);  // 1秒待機
  console.log('End');
})();

以下のコードではこの wait 関数を使って待機処理を再現している。

ブラウザ・Node.js 両方 : performance.now()

performance.now() は、ブラウザでも Node.js でも使える。現状、Node.js では perf_hooks からの require() が必要。

// Node.js の場合のみ、次のように require() する
const { performance } = require('perf_hooks');

const performanceNow = async () => {
  console.log('performance.now() : Start');
  const start = performance.now();
  await wait(1000);
  const end = performance.now();
  const result = { start, end, time: end - start };
  console.log('performance.now() : End', result);
  return result;
};

// 実行結果例 : 単位はミリ秒
// performance.now() : Start
// performance.now() : End {
//   start: 57.258082032203674,
//   end: 1059.7935930490494,
//   time: 1002.5355110168457
// }

Node.js 専用 : process.hrtime()

Node.js 専用だが、process.hrtime() を使うとナノ秒の精度で計測できる。

const processHrtime = async () => {
  console.log('process.hrtime() : Start');
  const start = process.hrtime();
  await wait(1000);
  const end = process.hrtime(start);
  const result = { start, end };
  console.log('process.hrtime() : End', result);
  return result;
};

// 実行結果例 : 秒・ナノ秒の配列なので足し合わせる
//   end: [ 1, 679661 ] → 1.000679661 秒 = 1000.679661 ミリ秒
// process.hrtime() : Start
// process.hrtime() : End { start: [ 1036330, 270832676 ], end: [ 1, 679661 ] }

戻り値が [秒, ナノ秒] という配列になっているので、足し合わせることで実際の経過時間が分かる。process.hrtime() の引数に、事前に取得しておいた process.hrtime() の配列を入れることで、自動的に差分を計算してくれる。

ブラウザ・Node.js 両方 : console.time()

次は console.time()console.timeEnd() のペアで計測する方法。引数にタイマー名を適当に指定する。

const consoleTime = async () => {
  console.log('console.time() : Start');
  const start = console.time('my-timer');
  await wait(1000);
  const end = console.timeEnd('my-timer');
  const result = { start, end };
  console.log('console.time() : End', result);
  return result;
};

// 実行結果例 : 各関数自体に戻り値はない・console.timeEnd() の時点で自動的に出力される
// console.time() : Start
// my-timer: 1.002s  // Node.js の場合の出力例
// my-timer: 1000.2431640625 ms  // ブラウザの場合の出力例
// console.time() : End { start: undefined, end: undefined }

他の console 系の関数と同様、関数の戻り値はなし。console.timeEnd() の時点でコンソール出力されるのだが、Node.js で実行した場合は s (秒単位) で、ブラウザで実行した場合は ms (ミリ秒) で出力されていた。

Node.js 専用 : process.uptime()

なんかちょっと昔はコレぐらいしか計測に使える方法がなかった記憶があるんだけど、変わりましたね。w

本来 process.uptime() は Node.js プロセスの起動からの時間を出力するモノだが、その差分を取ることで確認できる。

const processUptime = async () => {
  console.log('process.uptime() : Start');
  const start = process.uptime();
  await wait(1000);
  const end = process.uptime();
  const result = { start, end, time: end - start };
  console.log('process.uptime() : End', result);
  return result;
};

// 実行結果例 : 単位は秒単位
// process.uptime() : Start
// process.uptime() : End { start: 3.059283585, end: 4.06004901, time: 1.000765425 }

他の関数がミリ秒やナノ秒での出力だったのに対して、コレだけ秒単位。

以上。