3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PlaywrightとChrome DevTools Protocol用いてWebページのメモリ使用量を計測する

Last updated at Posted at 2024-09-30

viviONグループでは、DLsiteやcomipoなど、二次元コンテンツを世の中に届けるためのサービスを運営しています。
ともに働く仲間を募集していますので、興味のある方はこちらまで。

はじめに

Webページのメモリ使用量をモニタリングする必要があったので、PlaywrightとCDPを用いて計測してみました。
Playwrightの解説は割愛します。

使用環境

  • node 20+
  • playwright@1.47.0

Chrome DevTools Protocol(CDP)とは

Chrome DevTools Protocol(CDP)は、Chromium、Chrome、その他のBlinkベースのブラウザを外部から操作するためのプロトコルです。CDPを利用することで、パフォーマンスの計測など、Devtoolで提供されている機能をプログラム経由で制御することが可能になります。

PlaywrightとCDPを用いてWebページのメモリ使用量を計測する

Playwrightを用いてWebページにアクセスし、CDP経由でメモリ使用量を計測してみます。

サンプルスクリプト

以下が今回解説するスクリプトです。

import { chromium } from "playwright";

async function main() {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  const client = await page.context().newCDPSession(page);

  await client.send("Performance.enable");
  await page.goto("https://example.com");

  // 必要であれば計測前にGCを実行する
  // await client.send('HeapProfiler.collectGarbage')
  const performanceMetrics = await client.send("Performance.getMetrics");

  const memoryMetrics = performanceMetrics.metrics.filter(
    (metric) =>
      metric.name === "JSHeapUsedSize" || metric.name === "JSHeapTotalSize"
  );

  console.log("Memory Metrics:", memoryMetrics);

  await browser.close();
}

main();

スクリプトを実行すると、以下のメトリクスを取得できます。

[
  {
    name: "JSHeapUsedSize",
    value: 874812,
  }, {
    name: "JSHeapTotalSize",
    value: 2260992,
  }
]

解説

  1. chromium.launch()でChromiumブラウザを起動し、新規ページを作成します

    const browser = await chromium.launch();
    const page = await browser.newPage();
    
  2. context.newCDPSessionを使用して、ページに対するCDPセッションを開始します

    const client = await page.context().newCDPSession(page);
    

  1. メトリクスの計測を有効にする

    CDPのPerformance.enableを呼び出してメトリクスの計測を有効にします。

    await client.send('Performance.enable');
    
  2. 対象のページに移動する

    page.gotoを使用して対象のWebページに移動します。

    await page.goto('https://example.com')
    
  3. パフォーマンスメトリクスを取得する

    CDPのPerformance.getMetricsを呼び出してメトリクスを取得します。
    必要であれば事前に HeapProfiler.collectGarbageを呼び出して、不要になったメモリを解放してください。

    // 必要であれば計測前にGCを実行する
    // await client.send('HeapProfiler.collectGarbage')
    const performanceMetrics = await client.send('Performance.getMetrics');
    
    const memoryMetrics = performanceMetrics.metrics.filter(
    (metric) => ['JSHeapUsedSize', 'JSHeapTotalSize'].includes(metric.name)
    );
    
    console.log('Memory Metrics:', memoryMetrics);
    

今回はメモリ関連以外のメトリクスは除外していますが、以下が計測可能な全てのメトリクスです。

全てのメトリクス
[
  {
    name: "Timestamp",
    value: 896268.163451,
  }, {
    name: "AudioHandlers",
    value: 0,
  }, {
    name: "AudioWorkletProcessors",
    value: 0,
  }, {
    name: "Documents",
    value: 3,
  }, {
    name: "Frames",
    value: 1,
  }, {
    name: "JSEventListeners",
    value: 0,
  }, {
    name: "LayoutObjects",
    value: 15,
  }, {
    name: "MediaKeySessions",
    value: 0,
  }, {
    name: "MediaKeys",
    value: 0,
  }, {
    name: "Nodes",
    value: 43,
  }, {
    name: "Resources",
    value: 0,
  }, {
    name: "ContextLifecycleStateObservers",
    value: 3,
  }, {
    name: "V8PerContextDatas",
    value: 4,
  }, {
    name: "WorkerGlobalScopes",
    value: 0,
  }, {
    name: "UACSSResources",
    value: 0,
  }, {
    name: "RTCPeerConnections",
    value: 0,
  }, {
    name: "ResourceFetchers",
    value: 3,
  }, {
    name: "AdSubframes",
    value: 0,
  }, {
    name: "DetachedScriptStates",
    value: 2,
  }, {
    name: "ArrayBufferContents",
    value: 0,
  }, {
    name: "LayoutCount",
    value: 0,
  }, {
    name: "RecalcStyleCount",
    value: 0,
  }, {
    name: "LayoutDuration",
    value: 0,
  }, {
    name: "RecalcStyleDuration",
    value: 0,
  }, {
    name: "DevToolsCommandDuration",
    value: 0.000014,
  }, {
    name: "ScriptDuration",
    value: 0,
  }, {
    name: "V8CompileDuration",
    value: 0,
  }, {
    name: "TaskDuration",
    value: 0.000016,
  }, {
    name: "TaskOtherDuration",
    value: 0.000002,
  }, {
    name: "ThreadTime",
    value: 0.000052,
  }, {
    name: "ProcessTime",
    value: 0.076343,
  }, {
    name: "JSHeapUsedSize",
    value: 874812,
  }, {
    name: "JSHeapTotalSize",
    value: 2260992,
  }, {
    name: "FirstMeaningfulPaint",
    value: 0,
  }, {
    name: "DomContentLoaded",
    value: 896268.128472,
  }, {
    name: "NavigationStart",
    value: 896267.363206,
  }
]

まとめ

今回はPlaywrightとCDPを用いてWebページのメモリ使用量を計測する方法を紹介しました。
Webページのメモリ使用量を継続的にモニタリングすることは多くないですが、ぜひ試してみてください。

参考

一緒に二次元業界を盛り上げていきませんか?

株式会社viviONでは、フロントエンドエンジニアを募集しています。

また、フロントエンドエンジニアに限らず、バックエンド・SRE・スマホアプリなど様々なエンジニア職を募集していますので、ぜひ採用情報をご覧ください。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?