Mach3.laBlog

細かすぎて伝わらないjQuery拡張 (23) “$.timing” – Advent Calendar 2016

この記事は賞味期限切れです。(更新から1年が経過しています)

$.timing は、User Timing API のラッパーです。 わずかな機能だけですが、非対応環境に擬似的に対応してみました。

User Timing API とは

User Timing APIは、Webページ上のパフォーマンスを計測するためのインターフェースです。 その役割と使い方は下記URLのエントリーで解説されています。

ものすごくざっくりと使い方を紹介すると、こんな感じ。

  • mark() を使って任意のタイミングでタイムスタンプを「マーク」として記録
  • measure() を使って、記録したマーク間の所要時間を計測
  • タイムスタンプは1/1000ミリ秒という高精度で記録される

執筆時点でのメジャーどころの対応状況は IE10+ / Edge / Firefox / Chrome / Opera 40+ となっていて、 IE9以前やSafari(iOS含)は非対応です。

$.timing

使い方

// マークを記録
$.timing.mark("foo");
$.timing.mark("bar");

// マーク間の所要時間を記録
$.timing.measure("from_foo_to_bar", "foo", "bar");

// 名前からタイムスタンプを取得
$.timing.get("from_foo_to_bar"); // => number

// 記録したマークを全て取得
$.timing.marks(); // => object

// 記録したメジャーを全て取得
$.timing.measures(); // => object
  • .mark(name) でそのタイミングのタイムスタンプを記録します
  • .measure(name, start, end) で、開始マークから終了マークまでの所要時間を記録します
  • .get(name) で名前からマーク・メジャーの時間を数値で取得します
  • .marks() / .measures() で記録したマーク・メジャーを全てオブジェクトで取得

Polyfill とは呼べないモノ

$.timing はほんの一部の機能しか実装していません。 また、擬似的に再現してみたとはいえ1/1000ミリ秒単位で計測はちょっと出来無さそうで、 Polyfillと呼ぶにはあまりに片手落ちですね。

core-js あたりでPolyfillを書いているかも?と思いましたが、 中の人が「無理デス」 とおっしゃっています。

Thanks for proposal, but it can’t be polyfilled – only little part and with serious limitations.
https://github.com/zloirock/core-js/issues/130

コード

$.timing = {
    _supported: ("performance" in window) && ("timing" in window.performance),
    _data: {},
    _start: (new Date()).getTime(),

    mark: function(name){
        if(this._supported){
            window.performance.mark(name);
        } else {
            this._data[name] = {
                type: "mark",
                startTime: (new Date()).getTime() - this._start
            };
        }
    },

    marks: function(){
        return this.getEntries("mark", "startTime");
    },

    measure: function(name, start, end){
        if(this._supported){
            window.performance.measure(name, start, end);
        } else {
            this._data[name] = {
                type: "measure",
                duration: this.get(end) - this.get(start)
            };
        }
    },

    measures: function(){
        return this.getEntries("measure", "duration");
    },

    get: function(name){
        if(this._supported){
            var items = window.performance.getEntriesByName(name);
            return items.length ? items[0].startTime : void 0;
        }
        return (name in this._data) ? this._data[name].startTime : void 0;
    },

    getEntries: function(type, key){
        var data = {};
        if(this._supported){
            window.performance.getEntriesByType(type)
            .forEach(function(item){
                data[item.name] = item[key];
            });
        } else {
            $.each(this._data, function(name, item){
                if(item.type === type){
                    data[name] = item[key];
                }
            });
        }
        return data;
    }
};

コメント

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*