• こんにちは

  • 今日話す内容

    • v8.5.0 からの変更点
    • Performance Timing API を使う場面
    • Performance Timing API の使い方
    • performance-measure
  • v8.5.0 からの変更点

  • v8.5.0 からの変更点

    Performance Entry の取得方法が変わっています。

    // v8.5.0 以前
    performance.getEntriesByType('measure')
    
    // v8.5.0 以降
    const obs = new PerformanceObserver((items) => {
      items.getEntries().forEach(entry => {
        this.measures.push(entry)
      })
    })
    obs.observe({ entryTypes: ['measure'] }); // 監視するイベントを指定する必要がある
    
  • 変更前の API を使っている node_modules が結構あります

    • v8.5.0 以前の時期につくられたものが npm に存在します
    • v8.x.x は2019/12でメンテナンスが終了
    • 2018/10/30 から v10.x.x が Active LTS
    • 2019/10/12 から v12.x.x も Active LTS Start
    • メンテナンスされていない modules があります
    • PR のチャンスですね
  • Performance Timing API を使う場面

  • ISUCON

  • ISUCON でリクエストの総数と秒数を計測

    • 最初にするのはボトルネックを探すこと
    • MySQL の slow query は当てにならない
    • 3秒かかるエンドポイントを数回呼ばれるよりも 0.1秒かかるエンドポイントを1000回呼ばれるほうが負荷が高い
    • 呼ばれた回数と時間の総数を計測したい
  • ISUCON でリクエストの総数と秒数を計測した

    以下のような数値を計測したい場面で使う API のお話です

    name                                              size  sum         max      min      mean
    ------------------------------------------------  ----  ----------  -------  -------  -------
    /buy                                               529  1379186.94  3843.30     0.03  2607.16
    /items/:item_id(^\d+).json                        1066   802732.08  3839.38     1.30   753.03
    /login                                             704   782362.84  4105.26   225.83  1111.31
    /settings                                          666   545591.99  3765.35     4.80   819.21
    /new_items/:root_category_id(^\d+).json            366   383428.45  4208.59   162.25  1047.62
    /new_items.json                                    126   145147.42  4250.52   217.48  1151.96
    /users/transactions.json                            50   111228.35  7035.00    45.94  2224.57
    
  • Performance Timing API で計測する方法

    以下の3点を覚えましょう

    • performance と performanceObserver を取得する
    • performance で計測したい箇所をセット
    • performanceObserver から計測結果を取得する
  • performance と performanceObserver を取得する

    perf_hooks には他にも様々な Class が用意されていますがとりあえずこの2つを覚えましょう

    const {
      performance,
      PerformanceObserver
    } = require('perf_hooks')
    
  • performance で計測したい箇所をセット

    mark, measure を実行すると PerformanceEntry が生成されます。

    async function main () {
      performance.mark('A');
      await sleep(1000)
      performance.mark('B');
      performance.measure('A to B', 'A', 'B');
    }
    
  • performanceObserver から計測結果を取得する

    PerformanceObserver 経由で PerformanceEntry を取得します。以下の例では measure だけを監視しています

    const obs = new PerformanceObserver((items) => {
      console.log(items.getEntries()[0]);
    });
    obs.observe({ entryTypes: ['measure'] });
    
  • 結果

    PerformanceEntry {
      name: 'A to B',
      entryType: 'measure',
      startTime: 79.28805,
      duration: 1.07386 }
    
  • もう少しシンプルな計測方法

    performance.now()はマイクロ秒単位の精度で値を取得できるのでDate.now()のミリ秒単位よりも正確に計測できます

    var t0 = performance.now();
    doSomething();
    var t1 = performance.now();
    console.log("Call to doSomething took " + (t1 - t0) + " milliseconds.");
    
  • performance.timerify(fn)

    名前付きの関数を計測する時に便利です。なんとなく頭の片隅に置いておくとよいでしょう。

    async function someFunction() {
      await sleep(100)
    }
    
    // markName が someFunction となる
    const wrapped = performance.timerify(someFunction);
    wrapped()
    
  • performance-measure

  • performance-measure

    先日npm publishしました
    https://www.npmjs.com/package/performance-measure

    async function main() {
      const m = new PerformanceMeasure()
      m.start('A')
      await sleep(100)
      m.end('A')
      console.log(m.stats())
    }
    
  • まとめ

    • v8.5.0 から Performance Timing API の interface 変わってます。
    • performance と performanceObserver を組み合わせて計測できます。
    • performance.now だけでも十分計測できます。Date.now よりも正確です。
    • performance.timerify(fn) は名前付きの関数を計測するのにとても便利です。
    • performance-measure に Star をください。
    • Javascript チョットワカルのでどなたか仕事ください。
  • ご静聴ありがとうございました

Item 1 of 21
[ja]Performance Timing API