【JavaScript】ブラウザの「プロファイラー」を使って遅いロジックを一発で特定しよう!

Web画面の開発をしているときに、次のような経験をしたことはありませんか?

「画面の描画に時間がかかってしまう!」
「ひとつひとつの処理がもっさりしてて遅い!」

こういうときにJavaScriptのコードを読んでみても、どこが遅いかよくわからないし、当てずっぽうに直そうとしてみても時間ばかりがかかってしまいます。

今回は、こんなときに役立つブラウザのパフォーマンス計測ツール「プロファイラー」の使い方をご紹介します!

対象の読者

この記事は次のような方向けです。

  • JavaScript、jQueryの開発者(フロントエンドに携わっている方)
  • 既存ロジックのパフォーマンスを改善したいが方法がわからない
  • パフォーマンス改善をよくやるが、いつも時間がかかってしょうがない
  • 遅いロジックは大体特定したが、どのように改善していいかわからない

速度改善はまず遅いところを特定することが大切

速度が遅い処理に出会ったときにまずやってしまいがちなことがあります。
それは、「ソースを見て、遅そうなロジックを直そうとすること」です。

プログラムは最善でなくとも動いてくれます。
ソースを見て悪いところを探した場合、いくらでも改善できるところは見つかるものです。

しかし、そのコードが本当に遅い原因かどうかはわかりません。

ソースコードから遅そうなところを見つけ出して、苦労して修正したけど1%も速くならなかった、というのはよくある失敗パターンです。

速度改善は「ベストでないところを直す」のではなく、「遅いところを直す」ことが大切なのです。

というわけで、まず遅い処理を見つけ出す必要があります。

速度計測のためのツール「プロファイラー」

プロファイラーというツールがあります。
これは多くのブラウザの開発者ツールに搭載されているツールで、Google ChromeやFirefox、IEにも搭載されています。

このツールを使うことで、JavaScriptのどのファイルの何行目の処理に何秒かかって、それが全体の何%の時間を占めているか、がわかります。
つまり、全部分かります。

このプロファイラーを使うことで、遅い処理を簡単に特定することができるのです。

実際にプロファイラーを使ってみる

サンプルプログラムの作成

プロファイラーの効果を皆さんに実際に体験して頂くために、まず皆さんのローカルPCにサンプルプログラムを作りましょう。

プログラムは簡単なHTMLとJavaScriptでできており、わざと特定の処理がとても遅くなっています。
この遅い処理をプロファイラーで特定してみましょう。

まずサンプルプログラムを配置する親フォルダを作成しましょう。
フォルダ名は何でも構いません。
今回は「sample」という名前で作成しています。


そのフォルダ以下に次の2つのファイルを作りましょう。
中身は空でOKです。

  • index.html
  • app.js

それぞれのファイルに次のコードをそのまま貼り付けて保存しましょう。
ファイルの編集はファイルを選択し、「右クリック」→「プログラムから開く」からメモ帳等で開いて編集してください。

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>sample html</title>
<script src="https://code.jquery.com/jquery-3.4.0.js"></script>
<script src="app.js"></script>
</head>
<body>
  <button id="sample_button">click!</button>
</body>
</html>

app.js

$(function() {
    $('#sample_button').click(function() {
        parentFunc1();
        parentFunc2();
        alert('complete!');
    })
})


function parentFunc1() {
    func1();
    for (var i = 0; i < 50; i++) {
        func2();
        func3();
    }
}

function parentFunc2() {
    for (var i = 0; i < 1000; i++) {
        func3();
    }
}

function func1() {
    for (var i = 0; i < 2000000; i++) {
        $('#sample_button');//要素を取得しているだけで何もしていない
    }
}

function func2() {
    for (var i = 0; i < 1000; i++) {
        $('button');//要素を取得しているだけで何もしていない
    }
}

function func3() {
    for (var i = 0; i < 200; i++) {
        $('body');//要素を取得しているだけで何もしていない
    }
}

ソースが書けたら、index.htmlをブラウザから開きましょう。

index.htmlを右クリック → 「プログラムから開く」
→ Microsoft Edgeを選択

すると、真っ白な画面に1つだけボタンが表示されます。
このボタンはメッセージダイアログを表示するだけのボタンですが、メッセージが表示されるまでに数秒かかりとても遅いです。
実際に実行してみてください。

「complete!」というメッセージが表示されるまでに数秒かかりましたね?
この処理がなぜ遅いのか、プロファイラーで調査してみましょう。

プロファイラーで処理を記録する

今回はMicrosoft Edgeのプロファイラーを使います。
Edgeのプロファイラーは他のブラウザのものに比べてわかりやすく、使いやすいのでオススメです。

まず、サンプルプログラムの画面が開いている状態で、F12を押して開発者ツールを立ち上げましょう。
(うまく立ち上がらない場合は、アドレスバーをクリックしてからF12を押してみてください。)

開発者ツールが立ち上がったら、画面上部から「パフォーマンス」タブを選択します。

この画面でプロファイリングが実行できます。

プロファイルの大まかな流れは次の通りです。

  1. プロファイリングを開始
  2. 問題の処理を実行
  3. プロファイリングを停止

プロファイラーは開始されてから終了されるまでの間に実行されたJavaScriptの処理を記録してくれます。

それでは実際にプロファイリングしてみましょう。
画面中央の「プロファイリングを開始してパフォーマンスセッションを開始」(①)または画面左上の緑色の三角ボタン(②) を押してください。


これによりプロファイリングが開始されます。

その後、サンプルプログラムに戻って、問題のボタンをクリックしましょう。メッセージダイアログが表示されるまで待ちます。この間、プロファイラーは実行されたJavaScriptの処理を記録してくれています。

メッセージダイアログが表示されたらプロファイラーに戻って、プロファイリングを停止します。③か④から停止することができます。

記録された結果を分析する

プロファイリングを停止してしばらくすると結果が表示されるので、続けて「JavaScriptコールスタック」を開きましょう。
すると、実行された関数が一覧で表示されます。

この一覧はツリー構造になっていて、関数の中で呼び出している関数、さらにその関数から呼び出している関数、といった具合にドリルダウンして詳細を調べることができます。

いくつか関数をドリルダウンしてみていくと、parentFunc1とparentFunc2が表示されるので確認してください。

この結果から次のようなことがわかります。

関数名処理時間(ミリ秒)全体からみた割合(%)ソース・ファイル
parentFunc1196978.01app.js
parentFunc253721.28app.js

ここから、

「どうやらparentFunc1が処理の大部分の時間を占めている、どうやら問題がありそうだ」

ということがわかるのです。

続けて、parentFunc1をドリルダウンしてみましょう。

今度は関数が3つでてきました。
同様に表にまとめると次のようになります。

関数名処理時間(ミリ秒)全体からみた割合(%)ソース・ファイル
func1180471.47app.js
func21405.55app.js
func3250.99app.js

どこが悪そうかわかりますね?
func1が全体の71%の時間を使っているので、どうやらfunc1が悪そうです。

プロファイラーは直接ソースコードにジャンプすることも可能です。

func1 を選択した状態でEnterキーを押すとソースコードにジャンプできます。

ものすごい回数のループが
今回は、ループが200万回も実行されていることが原因でした。

まとめ

速度改善はまずどこが遅いのかを理解することから始まります。

今回のサンプルプログラムで学んだようにプロファイラーを使うことで、
時間がかかっているJavaScriptのロジックをスムーズに特定することができます。

その結果、あなたは遅くなっている処理とその理由を確実に把握した上で修正に専念することができます。

効率的に開発を進めるためにもプロファイラーを有効活用しましょう。

今回の例は単純にループを大量に実行しただけでしたが、次回は実際によくあるJavaScriptの遅いコードとそれに対応した速度改善方法を説明します。

ここまで読んでくださってありがとうございます!

もしこの記事が役にたったよ!面白かったよ!という方は下のボタンより、
twitterやFacebookでシェアいただけると嬉しいです!
twitterのフォローもお待ちしています!

次回もよろしくおねがいします!