Long Tasks API を実行して、サイト上の遅いスクリプトを調べる


超速! Webページ速度改善ガイド ── 使いやすさは「速さ」から始まる (WEB+DB PRESS plus) | 佐藤 歩, 泉水 翔吾 |本 | 通販 | Amazon を読んでいたところ、Long Tasks API 1 についての記載があり、興味を持ちましたので Blog 上に仕込んで実行してみました。
結果を以下に記載します。


参考


Long Tasks API とは

50ms 以上 時間がかかる Task の処理を、記録できる API です。
現在(2018/01/27) v1 で、Status が Editor’s Draft なので、今後も変更が入りそうな雰囲気です。1


実行方法

PerformanceObserver を登録する

ScriptAutoRunner - Chrome ウェブストア をインストールして、以下のスクリプトを登録します。

var aPE = [];
var observer = new PerformanceObserver(function(list) {
        var perfEntries = list.getEntries();
        for (var i = 0; i < perfEntries.length; i++) {
            var p = perfEntries[i];
            aPE.push(p);
        }
    });
observer.observe( { entryTypes: ["longtask"], buffered: true } );
buffered: true は、サンプルコード上に記載されていましたが、参考記事に現状は未実装で機能していないとの記載がありました。

チェックしたいページを開き、Console 上でスクリプトを実行する

kemsakurai.github.io で、以下のスクリプトを実行しました。

console.log(aPE);
以下、出力されます。
(5) [PerformanceLongTaskTiming, PerformanceLongTaskTiming, PerformanceLongTaskTiming, PerformanceLongTaskTiming, PerformanceLongTaskTiming]
0:PerformanceLongTaskTiming {attribution: Array(1), name: "self", entryType: "longtask", startTime: 1657.2000000000003, duration: 67.59999999999991}
1:PerformanceLongTaskTiming {attribution: Array(1), name: "self", entryType: "longtask", startTime: 1835.1400000000003, duration: 69.16999999999985}
2:PerformanceLongTaskTiming {attribution: Array(1), name: "cross-origin-descendant", entryType: "longtask", startTime: 1904.8550000000002, duration: 135.33999999999992}
3:PerformanceLongTaskTiming {attribution: Array(1), name: "multiple-contexts", entryType: "longtask", startTime: 2375.4000000000005, duration: 108.49999999999955}
4:PerformanceLongTaskTiming {attribution: Array(1), name: "unknown", entryType: "longtask", startTime: 5090.1, duration: 155.2549999999992}
length:5
__proto__:Array(0)

duration が100ms 以上のみ取得する

console.log(aPE.filter(function(element, index, array) {
    return (element.duration >= 100);
}));
以下、出力されます。
(3) [PerformanceLongTaskTiming, PerformanceLongTaskTiming, PerformanceLongTaskTiming]
0:PerformanceLongTaskTiming {attribution: Array(1), name: "cross-origin-descendant", entryType: "longtask", startTime: 1904.8550000000002, duration: 135.33999999999992}
1:PerformanceLongTaskTiming {attribution: Array(1), name: "multiple-contexts", entryType: "longtask", startTime: 2375.4000000000005, duration: 108.49999999999955}
2:PerformanceLongTaskTiming {attribution: Array(1), name: "unknown", entryType: "longtask", startTime: 5090.1, duration: 155.2549999999992}
length:3
__proto__:Array(0)

name が、 self のみ取得する

console.log(aPE.filter(function(element, index, array) {
    return (element.name == "self");
}));
以下、出力されます。
(2) [PerformanceLongTaskTiming, PerformanceLongTaskTiming]
0:PerformanceLongTaskTiming {attribution: Array(1), name: "self", entryType: "longtask", startTime: 1657.2000000000003, duration: 67.59999999999991}
1:PerformanceLongTaskTiming {attribution: Array(1), name: "self", entryType: "longtask", startTime: 1835.1400000000003, duration: 69.16999999999985}
length:2
__proto__:Array(0)
self は、自画面に遅いフレーム処理がある場合に記録されます。(と思います。)
name属性取り得る値は以下の通りです。

  • self
    自画面 の遅い Task

  • same-origin-ancestor
    同じdomain の 親フレームの遅い Task

  • same-origin-descendant
    同じdomain の 子フレームの遅い Task

  • same-origin
    同じdomain の 到達不能なフレームの遅い Task

  • cross-origin-ancestor
    他domain の 親フレームの遅い Task

  • cross-origin-descendant
    他domain の 子フレームの遅い Task

  • cross-origin-unreachable
    他domain の 到達不能なフレームの遅い Task

  • multiple-contexts
    遅い Task に複数のフレームコンテキストが関与している

  • unknown
    上記のどれでもない 遅い task

muliple-context と、unknown は、検知はしたけど 出どころがよくわからない Task に思えました。

Task 特定に必要な情報を取得する

Long Tasks with setTimeout test page を参考に、Task 特定に必要な情報を取得します。

aPE.forEach(function(element, index, array) {
    console.log("element.name:", element.name);
    console.log("element.startTime:" , element.startTime);
    console.log("element.duration:", element.duration);
    console.log("element.attribution.length:", element.attribution.length);
    console.log("element.attribution[0].name:", element.attribution[0].name);
    console.log("element.attribution[0].containerType:", element.attribution[0].containerType);
    console.log("element.attribution[0].containerSrc:", element.attribution[0].containerSrc);
});
VM1816:2 element.name: self
VM1816:3 element.startTime: 1598.98
VM1816:4 element.duration: 123.32500000000027
VM1816:5 element.attribution.length: 1
VM1816:6 element.attribution[0].name: script
VM1816:7 element.attribution[0].containerType: iframe
VM1816:8 element.attribution[0].containerSrc: 

VM1816:2 element.name: cross-origin-descendant
VM1816:3 element.startTime: 1765.6600000000003
VM1816:4 element.duration: 553.145
VM1816:5 element.attribution.length: 1
VM1816:6 element.attribution[0].name: script
VM1816:7 element.attribution[0].containerType: iframe
VM1816:8 element.attribution[0].containerSrc: https://platform.twitter.com/widgets/widget_iframe.83d5793f6ebbe2046330abda6016ae93.html?origin=https%3A%2F%2Fkemsakurai.github.io

以下、取得項目について説明します。

  • attribution[0].name
    PerformanceLongTaskTiming は、TaskAttributionTiming の 配列を保持しており、その1要素目の name 属性を取得します。
    現在は、script しか設定されていないようです。

  • element.attribution[0].containerType
    “iframe”、 “embed”、 “object”などのフレームコンテナの型が設定されています。
    確認した画面では、iframe のみが設定されていました。

  • element.attribution[0].containerSrc
    フレームコンテナの、接続リソースの URL が設定されます。
    他 domain に接続しているフレームでは、そのURLが設定されていました。


使って見た感想

  • 現在は、有用な情報は取得できない。
    監査と、パフォーマンス調査に使用するには、取得できる情報が少ないです。
    今後詳細な情報が取得でき、具体的な問題箇所まで特定できるとうれしいかなと思いました。

  • 遅い Task があるかどうかのチェックには使える。
    現在の情報でも、遅い Task が存在するかどうかはわかるので、パフォーマンス改善のボトルネック検知には使用できそうに思います。
    「200ms かかっている Task があったら改善箇所がないか確認する」などはいいかもしれません。

  • 使用方法のイメージ

    • RUM として、Google Analytics に送信する。
    • 開発テスト時の監査項目にする。

以上です。


  1. 個人的に、スクリプト処理の遅さを検知できるAPIだと思いました。フレームは、60 (フレーム・パー・) セカンズ:Pinterestの描画パフォーマンス最適化のケーススタディ | デザイン | POSTD を指しているのかと思いましたが、何か違う気もします。 

コメント