Puppeteer Performance.getMetrics で取得可能な指標について

Cover Image for Puppeteer Performance.getMetrics で取得可能な指標について
monotalk
monotalk

Puppeteerを少し触っているが、Chrome DevTools にアクセスができ、Performance.getMetrics() という指標が取得できることがわかった。
取得方法は、Puppeteerの Chrome DevTools Protocol のAPI clientを使用する方法と、page.metrics() を使用する方法がある。

Chrome DevTools Protocol の API client を使用する

  • コード

以下は、http://www.monotalk.xyz にアクセスして、取得したPerformanceMetricsをコンソール出力している。

const puppeteer = require('puppeteer');    
async function getPerformanceMetrics(page) {
  const { metrics } = await page._client.send('Performance.getMetrics')
  return metrics.reduce((acc, i) => ({ ...acc, [i.name]: i.value }), {})
}

async function waitForFMP(page) {
  let doneMet = null
  while (true) {
    const data = await getPerformanceMetrics(page)
    if (data.FirstMeaningfulPaint !== 0) {
      doneMet = data
      break
    }
    await new Promise(resolve => setTimeout(resolve, 300))
  }
  return doneMet
}

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  const client = await page.target().createCDPSession();
  await client.send('Performance.enable');
  await page.goto('http://www.monotalk.xyz');
  const performanceMetrics = await waitForFMP(page);
  console.log(performanceMetrics);
  await browser.close();
})();
  • コンソール出力結果
    コンソール出力結果は以下のようになる。
{ Timestamp: 70943.826105,
  AudioHandlers: 0,
  Documents: 13,
  Frames: 13,
  JSEventListeners: 130,
  LayoutObjects: 1633,
  MediaKeySessions: 0,
  MediaKeys: 0,
  Nodes: 1590,
  Resources: 141,
  ScriptPromises: 0,
  ContextLifecycleStateObservers: 2,
  V8PerContextDatas: 22,
  WorkerGlobalScopes: 1,
  UACSSResources: 0,
  RTCPeerConnections: 0,
  ResourceFetchers: 15,
  AdSubframes: 0,
  DetachedScriptStates: 9,
  LayoutCount: 28,
  RecalcStyleCount: 50,
  LayoutDuration: 0.399549,
  RecalcStyleDuration: 0.153554,
  ScriptDuration: 0.424509,
  V8CompileDuration: 0.015287,
  TaskDuration: 1.209604,
  TaskOtherDuration: 0.231992,
  ThreadTime: 1.027007,
  JSHeapUsedSize: 18031408,
  JSHeapTotalSize: 41730048,
  FirstMeaningfulPaint: 70942.258126,
  DomContentLoaded: 70941.905677,
  NavigationStart: 70941.46951 }

FirstMeaningfulPaint: 70942.258126,が取得できている。

page.metrics() を使用する

こちらは、良い待ち方が見つからなかったので、page.waitFor(1000); で1秒待ってから、metricsを取得することにした。

  • コード
const puppeteer = require('puppeteer');     
(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('http://www.monotalk.xyz');
    await page.waitFor(1000);
    const metrics = await page.metrics();
    console.log(metrics);
    await browser.close();
})();
  • コンソール出力結果
    コンソール出力結果は以下のようになる。
{ Timestamp: 70944.301509,
  Documents: 14,
  Frames: 14,
  JSEventListeners: 127,
  Nodes: 1617,
  LayoutCount: 27,
  RecalcStyleCount: 51,
  LayoutDuration: 0.30338,
  RecalcStyleDuration: 0.151848,
  ScriptDuration: 0.398699,
  TaskDuration: 1.085527,
  JSHeapUsedSize: 19306800,
  JSHeapTotalSize: 41992192 }

FirstMeaningfulPaintは取得できていない。

  • supportedMetrics
    puppeteerのコードを見たら理由がわかった。 puppeteer/Page.js at master · GoogleChrome/puppeteer
    に、取得対象のmetricsが記載されており、FirstMeaningfulPaint の記載はなかった。
    以下に、関連するコードを貼り付けておく。

/**
 * @return {!Promise<!Metrics>}
 */
async metrics() {
    const response = await this._client.send('Performance.getMetrics');
    return this._buildMetricsObject(response.metrics);
}

/**
 * @param {?Array<!Protocol.Performance.Metric>} metrics
 * @return {!Metrics}
 */
_buildMetricsObject(metrics) {
    const result = {};
    for (const metric of metrics || []) {
    if (supportedMetrics.has(metric.name))
        result[metric.name] = metric.value;
    }
    return result;
}

/** @type {!Set<string>} */
const supportedMetrics = new Set([
'Timestamp',
'Documents',
'Frames',
'JSEventListeners',
'Nodes',
'LayoutCount',
'RecalcStyleCount',
'LayoutDuration',
'RecalcStyleDuration',
'ScriptDuration',
'TaskDuration',
'JSHeapUsedSize',
'JSHeapTotalSize',
]);

page.metrics() で取得可能な指標の説明

puppeteer/api.md at master · GoogleChrome/puppeteer
に英語での説明があるので、日本語に訳す。

Timestamp The timestamp when the metrics sample was taken.
Documents Number of documents in the page.
Frames Number of frames in the page.
JSEventListeners Number of events in the page.
Nodes Number of DOM nodes in the page.
LayoutCount Total number of full or partial page layout.
RecalcStyleCount Total number of page style recalculations.
LayoutDuration Combined durations of all page layouts.
RecalcStyleDuration Combined duration of all page style recalculations.
ScriptDuration Combined duration of JavaScript execution.
TaskDuration Combined duration of all tasks performed by the browser.
JSHeapUsedSize Used JavaScript heap size.
JSHeapTotalSize Total JavaScript heap size.

Timestamp メトリクスを取得した時の、タイムスタンプ。
Documents ページのdocumentsの数。
Frames ページのフレームの数。
JSEventListeners ページのJavaScriptイベントの数。
Nodes ページのDOM Nodeの数。
LayoutCount ページすべて、またはページ一部のレイアウトの合計数。
RecalcStyleCount ページの再計算されたスタイルの総数。
LayoutDuration すべてのページレイアウトの合計時間。
RecalcStyleDuration ページスすべてのスタイルの再計算の合計時間。
ScriptDuration JavaScriptの実行の合計時間。
TaskDuration ブラウザによって実行されたすべてのタスクの合計時間。
JSHeapUsedSize 使用されているJavaScriptヒープサイズ。
JSHeapTotalSize JavaScriptの合計ヒープサイズ。

レイアウト、スタイルの再計算については、以下に記載がある。


FirstMeaningfulPaint を取得するなら

今のところは、Chrome DevTools Protocol のAPI clientを使用する。


参考