JavaScript で実行時間計測

# JavaScript で実行時間計測

JavaScript で実行時間を計測する方法は幾つかありますがここでは

- Performance インターフェース
- console オブジェクト

を使った方法のみ記述します。

# Performance インターフェース

Performance インターフェースを利用して実行時間を計測出来ます。
これには、`window.performance` もしくは 単に `performance` でアクセスできます。

## 解像度および単位

|||
|:--|:--|
|精度|5μs(マイクロ秒)|
|返り値の単位|ms(ミリ秒)|
|monotonic|Yes|
ただし、精度は、環境や設定によってはこれより大きい値になってしまう事もあるようです。

## 一番単純な使い方

一番単純な使い方は、`performance.now()` を用いる方法です。
計測したい処理の前後で`performance.now()`を呼び、その差分を取ります。
具体的には、以下のようなコードになります。

```javascript
const start = performance.now();
// 実行時間を計測した処理
const end = performance.now();
console.log(end - start);
```

開発段階で一時的に計測したいなどほとんどの場合は、これで十分かと思います。
もう少ししっかりした方法もあります。

## 定点観測

実行時間の計測をしっかりと組み込んでおきたい場合は、

- `performance.mark()`: 呼び出した時点に名前を付けて`timestamp`を作成する。
- `performance.measure()`: `timestamp` 間に名前を付けて`timestamp`を作成する。
- `performance.getEntries()`: 全ての`timestamp`を取得する。
- `performance.getEntriesByName()` `name` が一致する全ての`timestamp`を取得する。
- `performance.getEntriesByType()` `type` が一致する全ての`timestamp`を取得する。

を使うと便利です。
まず、`performance.mark()`で特定時点にマーク(`timestamp`)を作成します。
マークを 2 つ以上作成したら、`performance.measure()`で`timestamp`間の計測をします。
そして、`performance.getEntries()`, `performance.getEntriesByName()`, `performance.getEntriesByType()` のどれかで情報を取得します。
具体的には、以下のような使い方になります。

```javascript
function func1() {
  console.log("func1");
}
function func2() {
  console.log("func2");
}
function func3() {
  console.log("func3");
}

performance.mark("start"); // この時点での`timestamp`を作成している
func1();
performance.mark("point1");
func2();
performance.mark("point2");
func3();
performance.mark("end");

performance.measure("func1Time", "start", "point1"); // start-point1間の実行時間を計測する。つまりfunc1の実行時刻を計測する。
performance.measure("func2Time", "point1", "point2");
performance.measure("func3Time", "point2", "end");
performance.measure("allTime", "start", "end");

// measureで計測した`timestamp`は、typeが"measure"になるのでそれを全て取得して表示させる
for (const entry of performance.getEntriesByType("measure")) {
  console.log(`${entry.name}: ${entry.duration}`);
}
```

上記のコードでは、`performance.mark()`を使って、

- `func1()` の実行前の時点に、名前が `start` のマークを作成
- `func2()` の実行前の時点に、名前が `point1` のマークを作成
- `func3()` の実行前の時点に、名前が `point2` のマークを作成
- `func3()` の実行後の時点に、名前が `end` のマークを作成

をそれぞれしています。
その後、`performance.measure()`を使って

- マーク `start` とマーク `point1` の間を、`func1Time` という名前にして`timestamp`を作成
- マーク `point1` とマーク `point2` 間を、 `func2Time` という名前にして`timestamp`を作成
- マーク `point2` とマーク `end` 間を、 `func3Time` という名前にして`timestamp`を作成
- マーク `start` とマーク `end` 間を、 ` allTime` という名前にして`timestamp`を作成

をそれぞれしています。
ここまででは、`timestamp`を作成しただけで肝心の実行時間を得られていないので、`performance.getEntriesByType()` を使って取得します。
`performance.measure()`で作成した`timestamp`は、`type`が`"measure"`なのでこれで全てのものが取得できます。

# console オブジェクト

時間計測は、console オブジェクトのメソッドを使っても出来ます。
console オブジェクトには、 window.console もしくは 単に console でアクセス出来ます。
使用するメソッドは、

- console.time()
- consele.timeLog()
- console.timeEnd()

となります。

## 解像度および単位

|||
|:--|:--|
|精度|ms(ミリ秒)以下|
|返り値の単位|ms(ミリ秒)|
|monotonic|?|

## 使い方

```javascript:JavaScript
function func() {
  console.time("func"); // 計測開始
  for (let i=0; i<10; ++i) {
    console.timeLog("func"); // 必要に応じて
  }
  console.timeEnd("func"); // 計測終了
}
```

まずは、時間計測を開始したい位置で、console.time() を実行します。
ここで渡した文字列が計測期間を表すタイマーの名前になります。

そして、計測を終了したい位置で、console.timeEnd() を実行します。
ここでは、対応するタイマーの名前を渡します。
実行するとコンソールに実行時間が表示されます。

途中経過を表示したいならば console.timeLog() にタイマーの名前を渡して実行します。
console.timeLog() を実行すると対応する console.time() からの経過時間がコンソールに表示されます。