<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="http://organizeseries.com/"
	>

<channel>
	<title>Navigation Timing &#8211; HTML5Experts.jp</title>
	<atom:link href="/tag/navigation-timing/feed/" rel="self" type="application/rss+xml" />
	<link>https://html5experts.jp</link>
	<description>日本に、もっとエキスパートを。</description>
	<lastBuildDate>Sat, 07 Jul 2018 03:14:05 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.7.19</generator>
	<item>
		<title>Navigation Timingだからできる、Webアプリを俯瞰したパフォーマンス計測(3/3)</title>
		<link>/furoshiki/6335/</link>
		<pubDate>Fri, 09 May 2014 00:00:31 +0000</pubDate>
		<dc:creator><![CDATA[川田寛]]></dc:creator>
				<category><![CDATA[システム開発]]></category>
		<category><![CDATA[Navigation Timing]]></category>
		<category><![CDATA[パフォーマンス]]></category>

		<guid isPermaLink="false">/?p=6335</guid>
		<description><![CDATA[連載： パフォーマンスチューニング (11)いよいよHTMLドキュメントのダウンロードと、画面上への表示です。この動作の仕組みから、TATの「終了」がいつなのかを追ってみましょう。「終了」についてはかなり奥が深く、Web...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/performance-tech/" class="series-149" title="パフォーマンスチューニング" data-wpel-link="internal">パフォーマンスチューニング</a> (11)</div><p>いよいよHTMLドキュメントのダウンロードと、画面上への表示です。この動作の仕組みから、TATの「終了」がいつなのかを追ってみましょう。「終了」についてはかなり奥が深く、Web標準でもそのプロセスを「<a href="http://www.w3.org/TR/html5/syntax.html#the-end" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">The End</a>」として定義はしていますが、それだけでは語りきれない難しさがあります。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2014/05/05.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/05/05.png" alt="05" class="alignnone size-medium wp-image-6353" srcset="/wp-content/uploads/2014/05/05.png 640w, /wp-content/uploads/2014/05/05-300x262.png 300w, /wp-content/uploads/2014/05/05-207x180.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<h2>4. TCP接続、5. HTTPリクエスト/レスポンス</h2>

<p>名前解決で得られたIPアドレスを使って、HTMLドキュメントが置かれたサーバへ「4. TCP接続」します。いわゆる、<a href="http://ja.wikipedia.org/wiki/3%E3%82%A6%E3%82%A7%E3%82%A4%E3%83%BB%E3%83%8F%E3%83%B3%E3%83%89%E3%82%B7%E3%82%A7%E3%82%A4%E3%82%AF" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">3ウェイハンドシェーク</a>というものです。サーバとの接続交渉が終わると、HTTPリクエストをサーバへ送信し、HTTPレスポンスを受け取ります。</p>

<p>HTTPレスポンスの結果からリダイレクトであることが発覚した場合、「2. キャッシュ確認」からやり直しです。この、リダイレクト動作にかかった時間もNavigation Timingでは取得でき、「<a href="http://www.w3.org/TR/navigation-timing/#dom-performancetiming-redirectstart" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">redirectStart</a>」「<a href="http://www.w3.org/TR/navigation-timing/#dom-performancetiming-redirectend" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">redirectEnd</a>」の各プロパティを通じて取得することができます。</p>

<p>HTTPレスポンスから得られたデータは、いったん蓄積され、この後のDOMの生成で利用されることになります。</p>

<h2>6. DOM生成</h2>

<p>さて、ここからがブラウザの一番の見せ場、サーバから受信したHTMLドキュメントからDOMを生成し、描画を行うフェーズです。</p>

<p>HTML5のスペック「<a href="http://www.w3.org/TR/html5/syntax.html#parsing" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">8.2章 Parsing HTML documents</a>」に内部的な動作が定義されており、これに従い計測値が取得されます。このフェーズで意識すべきなのが、「①. HTMLドキュメント自体の読み込みを行っている段階(domLoading)」と「②. HTMLドキュメントの読み込みが完了し非同期に取得できる画像などのリソースを読み込んでいる段階(domInteractive)」の、2段階のステージです。</p>

<p>1段回目、domLoadingの段階。HTMLドキュメントの読み込みには、8KBというマジックナンバーが隠されています。これは、ブラウザがHTMLドキュメントの内容をパースする際に、一括で読み込みを行う単位と考えると良いでしょう。ブラウザはサーバから受信したHTMLドキュメントを、8KBずつ逐次パースし、DOM Contentを作っていきます。</p>

<p>JavaScript/CSSのような即時で反映する必要があるファイルの参照があった場合、HTMLドキュメントの受信は継続しますが、HTMLパース処理は停止し、JavaScript/CSSのコンパイルと実行を優先します。</p>

<p>DOM Contentの生成が終わった状態を、HTML5のスペックでは「interactive」と定義しています。JavaScriptにて「<a href="http://www.w3.org/TR/html5/index.html#events-0" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">DOMContentLoadedイベント</a>」を登録していた場合は、このタイミングで発火します。</p>

<h2>7. リソース読み込み</h2>

<p>ここからは、2段階目の説明に入ります。HTMLドキュメントが全て読み込まれ、画像などの非同期で読み込めるリソースを読み込んでいる段階です。先ほども説明しましたが、Web標準ではこの段階のことをinteractive(対話可能)と呼んでおり、名前の通り、画像の読み込み完了を待たずしてユーザからの入力を受付けることができます。</p>

<p>実は、ブラウザはHTMLドキュメントを読み込みつつリアルタイムに画面上へ表示する(ChromeはHTMLドキュメントのダウンロード完了時に表示する)という実装なため、「6. DOM生成」の段階でも既に入力可能だったりします。どちらをTATの開始と呼ぶべきか、非常に悩ましいところです。</p>

<p>画像の読み込みが完了し、Webページが完成したタイミングで「complete」という状態に推移します。completeへ推移すると、JavaScriptのloadイベントが発火します。ここで再び、ブラウザはJavaScriptの処理を動かすために、入力をブロックさせたりします。場合によっては、この段階でユーザからの入力を受け付けるために必要な、初期化処理を行なったりもします。例えば、jQueryの有名なプラグインであるDatePickerなんかは、loadイベント内で設定することが多く、ここに来るまでフォーカスを当ててもカレンダが表示されません。interactiveなんて言われていますが、実際にはloadイベントを実行するまではTATの終了とは言えないような気もしますね。ここまでくると、もはや終了の概念そのものをどう定義すべきかが、だんだんわからなくなってきました。</p>

<p>loadイベントの処理が完了すると、Navigation Timingで計測できる全ての処理が完了です。</p>

<p>なお、ここまでの過程で、JavaScriptやCSS、画像などの外部ファイルの読み込みを行っていますが、これら単独リソースごとの性能計測は、Web標準として少し扱いが異なります。詳しくは、「<a href="http://www.w3.org/TR/2014/CR-resource-timing-20140325/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Resource Timing</a>」を参照すると良いでしょう。</p>

<h2>何をもってTATとするか？</h2>

<p>ブラウザの仕組みについて一通り紹介したところで、TATを構成する要素が以下に分類できることが理解頂けたでしょう。この中のどこかに開始を作り、どこかに終了を作れば、あなたの求めるTATになるはずです！</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2014/05/08.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/05/08.png" /></a></p>

<p>開始候補、終了候補、なんて言葉を使ってみましたが、ここまでくるともはや、TATを取得することに意味があるのか？なんて思われても仕方ありません。実際のところ本当にその通りで、TATだけをピンポイントで取得しても、あまり役に立たなかったりします。</p>

<p>Navigation Timingはそもそも、ナビゲーションの動作の中から、性能のボトルネックを探すためのものです。生きた計測値を得るためのものです。ブラウザはナビゲーションを開始すると、様々なキャッシュを駆使して最小限で動作することを追求し、そして終了に向けて、DOM生成やリソースの取得、JavaScriptの初期実行を行い、最大限のポテンシャルを発揮しようとします。こうしたブラウザのメカニズムの中から、ボトルネックを探さなくてはいけないのですから、Navigation TimingはWebページの特性に合わせて、有用な情報を拾えるようにしなくてはいけません。</p>

<p>リソースの取得については「<a href="http://www.w3.org/TR/2014/CR-resource-timing-20140325/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Resource Timing</a>」、JavaScriptの性能に影響を与えるような処理に対しては、「<a href="http://www.w3.org/TR/hr-time/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">High Resolution Time</a>」のnow()なんかを利用して、計測を行うことが求められるでしょう。</p>

<p>パフォーマンスの改善は、まさに総合競技です。JavaScriptやCSS単独の高速化手法だけ知っててもダメだし、DBのパラメータチューニングだけできてもダメです。JavaやASP.NETやRuby On Railsも、全体から見ればほんの一部でしかありません。DNSやWebサーバ、APミドルなどのインフラも重要な構成要素ですし、私のようにイントラ向けのシステム開発を行なっている方はネットワーク装置の一台まで面倒を見ていることもあるでしょう。最近はクラウドも絡んできたりして、バックプレーンを共有する他社のWebアプリが性能に影響を与えるなんてのも聞いたことがあります。複雑化が進んでおり、ますます全体を見る目が求められているように思えます。</p>

<p>ところが、パフォーマンスの問題にぶつかると、どうしても自分の専門分野で見てしまい、DBだけを良くしようとしたり、JavaScriptだけを高速化しようと先走ってしまうことがあります。</p>

<p>Navigation Timingを入り口にして、生の測定値に基づき分析し、ブレークダウンしてみて下さい。きっとそれは、改善の近道となり、費用対効果の高い手段を見つけるヒントとなるでしょう。そしてWebアプリは、最高のパフォーマンスを得ることができるはずです。</p>

<ul>
<li><a href="https://html5experts.jp/furoshiki/6242/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Navigation Timingだからできる、Webアプリを俯瞰したパフォーマンス計測(1/3)</a></li>
<li><a href="https://html5experts.jp/furoshiki/6299/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Navigation Timingだからできる、Webアプリを俯瞰したパフォーマンス計測(2/3)</a></li>
</ul>
]]></content:encoded>
		
		<series:name><![CDATA[パフォーマンスチューニング]]></series:name>
	</item>
		<item>
		<title>Navigation Timingだからできる、Webアプリを俯瞰したパフォーマンス計測(2/3)</title>
		<link>/furoshiki/6299/</link>
		<pubDate>Thu, 08 May 2014 00:00:27 +0000</pubDate>
		<dc:creator><![CDATA[川田寛]]></dc:creator>
				<category><![CDATA[システム開発]]></category>
		<category><![CDATA[Navigation Timing]]></category>
		<category><![CDATA[パフォーマンス]]></category>

		<guid isPermaLink="false">/?p=6299</guid>
		<description><![CDATA[連載： パフォーマンスチューニング (10)前回の記事でもお伝えしたとおり、ブラウザのメカニズムが、TATの計測を複雑にしています。その事情について、まずTATの「開始」をどこにするかについて考え、紐解いてみましょう。W...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/performance-tech/" class="series-149" title="パフォーマンスチューニング" data-wpel-link="internal">パフォーマンスチューニング</a> (10)</div><p><a href="https://html5experts.jp/furoshiki/6242/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">前回の記事</a>でもお伝えしたとおり、ブラウザのメカニズムが、TATの計測を複雑にしています。その事情について、まずTATの「開始」をどこにするかについて考え、紐解いてみましょう。Web標準で定義するところのブラウザの動作について、少しだけデフォルメさせた処理モデルを使って、全体の流れを解説します。以下の図の赤字はtimingオブジェクト配下にあるプロパティ、数字が振ってある矢印は処理の流れです。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2014/05/c9e0e6e4f4b94208f34ad39a0948069f.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/05/c9e0e6e4f4b94208f34ad39a0948069f.png" alt="スクリーンショット 2014-05-02 5.23.34" class="alignnone size-medium wp-image-6320" srcset="/wp-content/uploads/2014/05/c9e0e6e4f4b94208f34ad39a0948069f.png 640w, /wp-content/uploads/2014/05/c9e0e6e4f4b94208f34ad39a0948069f-300x165.png 300w, /wp-content/uploads/2014/05/c9e0e6e4f4b94208f34ad39a0948069f-207x114.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<h2>0. ナビゲーション開始</h2>

<p>Webページの読み込み動作を、「ナビゲーション」と呼びます。ブラウザは、ネットワーク上のHTMLドキュメントにアクセスすると、Webページを構成する様々な情報を削除(アンロード)します。そして、新しくHTMLドキュメントを読み込み、DOMを構成し、JavaScriptやCSS、画像などのリソースを取得しながらWebページの描画を進めていきます。この一連の動作が、ナビゲーションです。</p>

<p>近年は、「<a href="http://en.wikipedia.org/wiki/Single-page_application" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">SPA(Single-page Application)</a>」と呼ばれるアーキテクチャがあり、DOM操作により画面遷移を擬似的に表現する手法もありますが、この仕組みではナビゲーションを開始できません。あくまで、JavaScript APIやプラグインの力を借りず、ブラウザの機能を使ってWebページを遷移させることで、ナビゲーションは開始されます。</p>

<p>ナビゲーションは、ハイパーリンクのクリックもあれば、Formを使ってサブミットすることでも発生します。戻る/進むボタンやリロードボタンを押下した際も、同様です。こうした、様々なナビゲーションを発生させるアクションは、ブラウザのキャッシュの動作、ナビゲーション全体の動作への影響が大きいため、<a href="http://www.w3.org/TR/navigation-timing/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Navigation Timing</a>を扱う際に理解することが求められます。</p>

<p>Web標準では、こうしたナビゲーションの種類を「<a href="http://www.w3.org/TR/navigation-timing/#sec-navigation-info-interface" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">PerformanceNavigation</a>」として以下のように分類しています。まずは、この定義を中心としてその違いを把握してみましょう。</p>

<ul style="border: silver 1px solid;padding:10px">
<li><a href="http://www.w3.org/TR/navigation-timing/#dom-performancenavigation-typenavigate" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">TYPE_NAVIGATE</a> : ハイパーリンクのクリック、ブックマーク等。</li>
<li><a href="http://www.w3.org/TR/navigation-timing/#dom-performancenavigation-typereload" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">TYPE_RELOAD</a> : ブラウザのリロードボタン押下。</li>
<li><a href="http://www.w3.org/TR/navigation-timing/#dom-performancenavigation-typebackforward" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">TYPE_BACK_FORWARD</a> : ブラウザの戻る/進むボタン押下。</li>
<li><a href="http://www.w3.org/TR/navigation-timing/#dom-performancenavigation-typereserved" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">TYPE_RESERVED</a> : 未定義のWebページ読み込みアクション。</li>
</ul>

<p><a href="https://html5experts.jp/wp-content/uploads/2014/05/04a.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/05/04a.png" alt="04a" class="alignnone size-medium wp-image-6310" srcset="/wp-content/uploads/2014/05/04a.png 546w, /wp-content/uploads/2014/05/04a-300x141.png 300w, /wp-content/uploads/2014/05/04a-207x97.png 207w" sizes="(max-width: 546px) 100vw, 546px" /></a></p>

<p>「TYPE_NAVIGATE」は、ハイパーリンクをクリックした際や、フォームをサブミットした際に発生する、一般的なナビゲーション動作です。ナビゲーションバーへURLを入力しEnterキーを押下した際、ブックマークを開いた際もこの動作であり、基本はこのアクションが選択されると想定すべきでしょう。後に説明する、「<a href="http://www.ietf.org/rfc/rfc2616.txt" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">RFC 2616</a>」のHTTP Cacheが最大限に活用されるのも、このナビゲーション動作です。</p>

<p>「TYPE_BACK_FORWARD」は、基本的には「戻る/進む」ボタンを押下した際に発生します。Web標準で言うところの「<a href="http://www.w3.org/TR/html5/browsers.html#history-traversal" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">履歴移動(History Traversal)</a>」により発生したナビゲーションです。ただ、「<a href="http://www.w3.org/TR/html5/browsers.html#scroll-to-fragid" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">フラグメント識別子(Fragment Identifier)</a>」を利用したURLを扱った場合、ナビゲーションを伴わないWebページ内の移動を行うことがあります。また、Webページが一定の条件を満足すると、ナビゲーション発生時に、前のWebページ全体をそのままキャッシュさせることで、戻るボタンのパフォーマンスを改善しようとします。このような動作を行なった場合、戻るボタンを押下してもナビゲーションは発生しません。</p>

<p>「TYPE_RELOAD」は、「リロードボタン(再読み込み)」を押下した際に発生します。ブラウザによってCtrl/Shiftとリロードボタンを同時押しすることで、HTTP Cacheの一切を破棄しWebページの再読み込みを行う「スーパーリロード(強制再読み込み)」と呼ばれる機能があります。Navigation Timingではこれを区別することなく「TYPE_RELOAD」として扱いますが、実際のキャッシュの動作は大きく異なるものとなるため、明確に区別する必要があります。</p>

<p>「TYPE_RESERVED」については未定義であり、ブラウザでWebページを扱っている範囲では、あまり意識する必要はありません。</p>

<h2>1. アンロード</h2>

<p>ナビゲーションが開始され、標準的なブラウザはまず「1. <a href="http://www.w3.org/TR/html5/browsers.html#unloading-documents" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">アンロード</a>」という処理を行います。ブラウザは、今表示しているWebページのリソースを破棄し、次のWebページを表示する準備をするわけです。DOMの情報を持つDOM Contentや、JavaScriptの機能の初期化を行います。</p>

<p>Web標準では、この処理を「<a href="http://www.w3.org/TR/html5/webappapis.html#handler-window-onunload" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">unloadイベント</a>」として捕捉でき、Navigation Timingを利用してイベント発生前後の時間を取得することができます。ただ、<em>このタイミングは常に一定しているとは限りません。<sup>(※ <a href="#01" data-wpel-link="internal">注１</a>)</sup></em>表面的には、アンロードはこのタイミングで発生しているように見せてはいますが、実装ではブラウザのレンダリングエンジンによってバラツキがあり、この処理の負荷が、この後説明するDOM読み込みのタイミングに大きな影響を与えることがあります。</p>

<p>また、「戻る/進む」ボタンを押下した場合の動作も独特です。先ほども少し説明しましたが、Webページは一定の条件を満足すると、アンロードを行わずメモリ上にWebページをまるごとキャッシュさせます。この動作は、例えばIE11だと<a href="http://msdn.microsoft.com/ja-jp/library/ie/dn265017(v=vs.85).aspx" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">デベロッパーセンター</a>、Firefoxだと<a href="https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">MDN</a>のドキュメントに仕組みが掲載されており、ブラウザごとにやや異なる思想を持っていることも把握できるはずです。HTML5の「<a href="http://www.w3.org/TR/html5/browsers.html#event-pageshow" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">pageshow</a>/<a href="http://www.w3.org/TR/html5/browsers.html#event-pagehide" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">pagehide</a>」イベントで捕捉でき、ある程度の制御が可能なわけですが、基本的にこの動作、ナビゲーションが発生しないのですから、Navigation Timingのプロパティの値も更新されません。</p>

<h2>2. キャッシュ確認</h2>

<p>標準的なブラウザがアンロードを終わらせると、「2. キャッシュ確認」を行います。Webページの表示に必要なHTMLドキュメントを、キャッシュの中から探すわけです。キャッシュと言っても、ブラウザのみで有効性判断ができるものあれば、サーバに問い合わせを行わないと判断できないものもります。ここでチェックされるのは、あくまで前者のみです。HTML5の「<a href="http://www.w3.org/TR/2011/WD-html5-20110525/offline.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">AppCache</a>」や、「<a href="http://www.ietf.org/rfc/rfc2616.txt" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">RFC 2616</a>(13.5)」で定義されたHTTPヘッダのプロパティ「Expires(14.2)」「Cache-Control max-age(14.9)」によるHTTP Cacheなんかは古くから活用されているため、ご存知の方も多いでしょう。</p>

<p>AppCacheは、常にこの段階で読み込みが行われます。しかし、HTTP Cache(Expires)により得られるゆるいキャッシュは、TYPE_NAVIGATEの場合のみ、ブラウザ内のキャッシュを利用します。この仕様は動作チェックの際に問題となることがあり、誤ってリロードボタンを押下してテストしようものなら、テスト担当者は一日を無駄に過ごすことになります。(※ アドレスバーにフォーカスを当ててEnterキーを押下、がキャッシュのテストの鉄則です！)</p>

<p>Chromeだけは、やや動作が例外的です。Chromeは、HTMLドキュメント内から参照されるJS/CSS/画像ファイルのようなリソースでも無い限り、HTTP Cacheによるブラウザ内のキャッシュを利用してくれません。XHR(XMLHTTPRequest)についても同様で、Chromeだけは必ずサーバへのアクセスを伴います。そもそも、Webページはサーバサイドのプログラムで動的に生成するのが殆どなので、HTMLドキュメントのキャッシュは期待できないものと見なすべきでしょう。</p>

<h2>3. 名前解決</h2>

<p>標準的なブラウザは、有効なキャッシュを発見できなかった場合、HTMLドキュメントが置かれているサーバの場所を特定するため「3. 名前解決」を行います。</p>

<p>名前解決については、Linux/OS X/iOS上のブラウザについては、基本的にDNS名として扱い名前解決を行います。しかし、Windows OS上のブラウザは、微妙に同じ動作にはなりません。Windows OS上のブラウザは、ドメイン名をフルコンピュータ名というやや特殊な概念として扱い、<a href="http://technet.microsoft.com/ja-jp/library/cc728142" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">NetBIOS(WINS)名とDNS名の2つの名前の概念を扱うハイブリッドな名前解決を行います</a>。</p>

<p>これは、ブラウザの仕様というより、OSの持つTCP/IPモジュールの仕様の違いです。IEとFirefox/Chromeとで異なるAPIをコールしていますが、どちらも最終的には同じ<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms740673(v=vs.85).aspx" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">WinSock2</a>の名前解決のメカニズムを利用します。名前解決を行うリゾルバにも、OSによる動作の違いがありますが、DNSを使っている限り、機能面において、ブラウザからはあまり意識する必要がありません。</p>

<p>インターネット向けでは、各プロバイダが提供するDNSサーバの性能が関わってくることもあります。DNSもやはり、キャッシュが要です。DNSを構成する各ノードのキャッシュの動作次第で、性能は大きく変化します。TTL設定のチューニング、DNS Prefetchを活用して対策してみると良いでしょう。</p>

<h2>キャッシュだらけ！</h2>

<p>ナビゲーションの動作のうち、どこをTATの開始とすべきか？もうお分かりと思いますが、キャッシュだらけで、前提条件から疑いにかからなくてはいけません！Webページ自体の(アンロード絡み)のキャッシュ、HTML5 AppCacheやRFC 2616によるブラウザ側のキャッシュ、名前解決絡みのキャッシュと、まだWebサーバにアクセスしていないというのに、これだけのキャッシュが絡んでいます。</p>

<p>最初にご紹介した「navigationStart」は、こうした前の画面の動作を含んだ計測値です。アンロードや、この後説明するリダイレクトを含めるとなると、開始をどこに置くのかというのもまた難しくなってきます。</p>

<p>TATの本当に難しさはここだけではありません。TATの「終了」の扱い、これも難しかったりします。ブラウザのメカニズムを掘り下げて追ってみましょう。</p>

<p>「Navigation Timingだからできる、Webアプリを俯瞰したパフォーマンス計測(3/3)」に続きます。(※5/9公開予定)</p>

<ul>
<li><a href="https://html5experts.jp/furoshiki/6242/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Navigation Timingだからできる、Webアプリを俯瞰したパフォーマンス計測(1/3)</a></li>
<li><a href="https://html5experts.jp/furoshiki/6335/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Navigation Timingだからできる、Webアプリを俯瞰したパフォーマンス計測(3/3)</a></li>
</ul>

<div style="line-height:110%"><a name="01" data-wpel-link="internal"></a><small>※注1 : 実装では、Chromeのアンロードはこのタイミングには行われていません。気になる方は、Chronium35であれば<a href="https://chromium.googlesource.com/chromium/blink/+/master/Source/core/loader/DocumentLoader.cpp" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">./core/loader/DocumentLoader.cpp(startLoadingMainResource)</a>を確認してみると良いでしょう。PerformanceTiming::markNavigationStart()の後にPerformanceTiming::markFetchStart()を呼び出しており、アンロードは遅延して実行していることが読み取れます。なお、Chromeのアンロードは、HTMLドキュメントのHTTP受信完了時に発生します。このあたりは、<a href="https://chromium.googlesource.com/chromium/blink/+/master/Source/core/loader/DocumentLoader.cpp" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">./core/loader/DocumentLoader.cpp(finishedLoading)</a>あたりが動作を理解するのに適しており、commitIfReady()の実装を掘っていくと、./core/loader/FrameLoader.cpp FrameLoader::commitProvisionalLoad→FrameLoader::closeURL…と進み、最終的にunloadイベント発火のタイミングをマークしている処理に到達します。</small></div>
]]></content:encoded>
		
		<series:name><![CDATA[パフォーマンスチューニング]]></series:name>
	</item>
		<item>
		<title>Navigation Timingだからできる、Webアプリを俯瞰したパフォーマンス計測(1/3)</title>
		<link>/furoshiki/6242/</link>
		<pubDate>Fri, 02 May 2014 03:00:11 +0000</pubDate>
		<dc:creator><![CDATA[川田寛]]></dc:creator>
				<category><![CDATA[システム開発]]></category>
		<category><![CDATA[Navigation Timing]]></category>
		<category><![CDATA[パフォーマンス]]></category>

		<guid isPermaLink="false">/?p=6242</guid>
		<description><![CDATA[連載： パフォーマンスチューニング (9)こんにちは、html5jパフォーマンス部、スタッフの川田です。5月8日ですが、私たちのコミュニティ主催で勉強会を開催することになりました！！ そして、残念なお知らせです。募集した...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/performance-tech/" class="series-149" title="パフォーマンスチューニング" data-wpel-link="internal">パフォーマンスチューニング</a> (9)</div><p>こんにちは、html5jパフォーマンス部、スタッフの川田です。5月8日ですが、私たちのコミュニティ主催で<a href="http://atnd.org/events/50159" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">勉強会</a>を開催することになりました！！</p>

<p><a href="http://atnd.org/events/50159" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/05/aeaf4d319ffa73eab4f8b831cc4b1850.png" alt="スクリーンショット 2014-05-02 3.49.38" class="alignnone size-medium wp-image-6268" srcset="/wp-content/uploads/2014/05/aeaf4d319ffa73eab4f8b831cc4b1850.png 640w, /wp-content/uploads/2014/05/aeaf4d319ffa73eab4f8b831cc4b1850-300x156.png 300w, /wp-content/uploads/2014/05/aeaf4d319ffa73eab4f8b831cc4b1850-1024x535.png 1024w, /wp-content/uploads/2014/05/aeaf4d319ffa73eab4f8b831cc4b1850-207x108.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p>そして、残念なお知らせです。募集した直後に、席が埋まってしまいました！せっかく、これだけ多くの方にパフォーマンスへ興味を持っていただいたのに、このままじゃもったいない！</p>

<p>なので本記事では、この勉強会で語られない、別の切り口からパフォーマンスについて語ってみようかと思います。内容は、私が技術評論社「<a href="http://gihyo.jp/magazine/SD" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Software Design 2014年5〜7月号</a>」にて連載しております、「Web標準技術で行う、Webアプリのパフォーマンス改善」で扱っているテーマの一部を、Web向けに書き直したものです。</p>

<h2>Webアプリのパフォーマンス計測は簡単なのか？</h2>

<p>パフォーマンスは、メモリを節約するものからCPUコストを下げるものまで、様々な種類があります。本記事では「ターンアラウンドタイム(TAT)」という指標値について考えてみましょう。</p>

<p><a style="float:left;margin-right:30px" href="/wp-content/uploads/2014/05/00.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/05/00-300x168.png" alt="00" width="300" height="168" class="alignnone size-medium wp-image-6245" srcset="/wp-content/uploads/2014/05/00-300x168.png 300w, /wp-content/uploads/2014/05/00-207x116.png 207w, /wp-content/uploads/2014/05/00.png 502w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>

<p>TATとは、アプリケーションの応答速度を表す指標の一つです。厳密には、あるアプリケーション・サーバに対して、ユーザが何かしらの操作・入力を行ってから、アプリが反応し終わり、ユーザが再び入力を受け付けることができるような状態になるまでの時間、と定義されています。Webページが遷移する時間を、定量的に評価できる指標値ということになります。</p>

<p>このTATという考え方、そんなにマニアックなものというものでもなく、レスポンスタイムやスループット、アベイラビリティなどと同様に、古くから存在する非機能要求の項目です。IPAの情報処理試験でもよく見かける、有名なキーワードに思えるでしょう。ところが、これをWebを検索しても、なかなかしっくりくる計測手段が見つかりません！この問題、特にWebに限定した話というものでもないはずです。GUIレベルでの性能計測は、昔からある悩みの一つで、アナログにストップウォッチの力を借りるなんてことも割とよく聞く話です。筆者もIE6全盛のWebアプリ開発で、同じ悩みを抱えたことがあります。</p>

<p>今回、そんなTATをめぐる悩みに対して、ちょっとしたヒントをご紹介します。ブラウザの仕組みを探り、WebアプリのTATとは何かを探り、そして標準的な手段の中からその計測方法について探ってみましょう。「そもそも、そんな指標で評価することに価値があるのか！？」なんて議論も生じていたりするのですが、その点は一番最後に触れるとして、今回はTATという切り口からWebページの性能について考えてみます。</p>

<h2>TATの計測で、Webサーバのログはアテになるのか？</h2>

<p>SPDYなどの新しいプロトコルのことは一旦忘れて、シンプルなHTTP1.Xを前提に考えてみて下さい。HTTP1.Xは、HTMLドキュメント取得し、HTMLドキュメント内で参照されている必要なJavaScript/CSS/画像などの外部リソースを、逐次取得し表示していくという仕組みです。サーバサイドで動的にHTMLを生成するようなアプリだと、画面を遷移する都度、最低でもHTMLドキュメント程度はサーバ側から取得することになります。</p>

<p>この動きに注目し、計測で非常によく利用されるのが、Webサーバログの「リクエスト処理時間(Time taken to process the request)」です。Apache HTTP Serverのアクセスログのフォーマットオプション「<a href="http://httpd.apache.org/docs/2.2/mod/mod_log_config.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">%D</a>」あたりは有名でしょう。このオプションは、HTTPリクエストを受け付けた瞬間から、サーバで処理が行われ、データを出力し終わるまでの時間を、マイクロ秒単位で計測する機能です。<a href="https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html#Access_Log_Valve/Attributes" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Tomcat</a>や<a href="http://docs.jboss.org/jbossweb/7.0.x/config/valve.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">JBoss</a>のようなJavaミドル、Microsoftの<a href="http://msdn.microsoft.com/ja-jp/library/cc338080.aspx#W3CExtendedLoggingDefinitions" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">IIS(Internet Information Services)</a>でも、リクエスト処理時間をミリ秒で計測できる機能を実装しており、大抵のWebアプリでは活用できるコモディティ化した機能と言えます。</p>

<p>リクエスト処理時間は、実際にサーバ上の問題を発見するのに価値が高い計測値です。運用時には、キャパシティプランニングの目安や、障害発生時の解析に活用されたりします。また、お客様と品質保証の明確な基準を決める「<a href="http://ja.wikipedia.org/wiki/%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E6%B0%B4%E6%BA%96%E5%90%88%E6%84%8F" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">SLA(Service-Level Agreement)</a>」でも、アクセスの何％を保障するかという「<a href="http://ja.wikipedia.org/wiki/%E5%88%86%E4%BD%8D%E6%95%B0#.E3.83.91.E3.83.BC.E3.82.BB.E3.83.B3.E3.82.BF.E3.82.A4.E3.83.AB" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">パーセンタイル</a>」を配慮した形で活用することがあります。どこにでも目にするこの計測値、一見すると使い道が広く、万能な値に見えるでしょう。</p>

<p>ところが残念なことに、リクエスト処理時間は、キャッシュされていないごく一部のファイル/プログラム単位の性能しか評価できません。サーバがどの程度のリクエストを捌けるのかを判断する「<a href="http://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%AB%E3%83%BC%E3%83%97%E3%83%83%E3%83%88" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">スループット(＝処理能力)</a>」の指標値として扱うには高い価値を発揮しますが、TATの指標値として扱うには、対象が局所的で、不足が大きすぎます。サーバから見ると性能は高いのに、クライアントで見ると画面はいつになっても白いまま！なんてことになりかねません。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2014/05/01.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/05/01.png" alt="01" class="alignnone size-medium wp-image-6289" srcset="/wp-content/uploads/2014/05/01.png 640w, /wp-content/uploads/2014/05/01-300x146.png 300w, /wp-content/uploads/2014/05/01-1024x501.png 1024w, /wp-content/uploads/2014/05/01-207x101.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p>では、TATを計測するにはどうすればよいのでしょうか？画面を表示する際のもっさり感の原因は、どのように探ればよいのでしょうか？このあたり、最近のWeb標準がかなり力を入れています。2012年12月にW3C勧告となった「<a href="http://www.w3.org/TR/navigation-timing/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Navigation Timing(ver.1)</a>」がまさにその代表的なスペックです。</p>

<p>Navigation Timingを含むWebのパフォーマンスに関する仕様は、2010年にW3Cで設立された「<a href="http://www.w3.org/2010/webperf/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Web Performance Working Group(WebPerf WG)</a>」で議論され、IE9+、Firefox、Chromeなどのブラウザにその成果が反映されています。Facebookのザッカーバーグ氏がHTML5に失望し、同社のアプリをネイティブに書き換えるという有名な事件がありますが、そんな彼らも同WGの設立直後すぐに反応し、WGの議論に参加しています。2013年には「Web vs ネイティブ」という議論が盛り上がりましたが、WebPerf WGの取り組みは、現在のWebが抱える性能という問題を見つめていく上で、注目すべき重要なポイントと言えるでしょう。</p>

<h2>Navigation Timingの使い方、TATの計測方法</h2>

<p>Navigation Timingでは、ハイパーリンクをクリックした瞬間からWebページが利用できるようになるまでを、ブラウザの内部的な動作である「<a href="http://www.w3.org/TR/navigation-timing/#processing-model" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">処理モデル(Processing Model)</a>」として定義し、その経過時間を取得することができます。</p>

<p>ブラウザ自体にも「開発者ツール」として計測のためのツールが備わっていますが、ブラウザごとに考え方も違うし、活用できる場も開発時のみと非常に限定的です。Navigation TimingはWeb標準なので、ブラウザに依存しない共通の考え方で計測値を扱え、また運用時にもJavaScript上で生のデータを収集することができる点で、開発者ツールより高いポテンシャルを得ています。</p>

<p>実際のJavaScriptの仕様を見ながら確認してみましょう。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2014/05/4e7e8507cc1b623c22b6842557767406.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/05/4e7e8507cc1b623c22b6842557767406.png" alt="02" width="300" height="99" class="alignnone size-medium wp-image-6295" /></a></p>

<p>windowオブジェクト配下にある「performance」は、パフォーマンス関連のJavaScript APIにアクセスするための入り口となるオブジェクトです。そのさらに下に、WebPerf WGの成果である様々なスペックの実装が分類別で並んでいます。そのうちのひとつである「timing」の配下には、ハイパーリンクをクリックしてから応答するまでの間に発生する、様々な動作発生時のタイムスタンプを取得できるプロパティが並んでいます。</p>

<p>TATを取得しコンソールに表示させる、シンプルなコードを確認し、使い方を掴んでみましょう。</p>

<p></p><pre class="crayon-plain-tag">/* timingオブジェクトの取得 */
var timing = ( window.performance || {} ).timing;
/* TATの計測 */
timing &amp;&amp; window.addEventListener( "load", function() {
    setTimeout( function() {
        var tat = timing.loadEventEnd - timing.navigationStart;
        console.log( "TAT = " + tat );
    },1);
},false);</pre><p></p>

<p>「timing.navigationStart」はハイパーリンクがクリックされた直後の時間、「timing.loadEventEnd」はWebページが表示されJavaScriptのloadイベントの処理が完了した直後の時間が取得できるプロパティです。サンプルでは、この2つの単純な差分を、仮にTATとしてみました。setTimeoutで実行時間を遅延させているのは、loadEventEndがloadイベント中だと未計測の状態「0」を返してしまうという問題への対策です。</p>

<p>このサンプルで得られる計測値が、TATとして「ほぼ正解」の値ということになります。ただ、ほぼ正解であって、完全な正解とは言えません。このあたりの理由については、ブラウザの内部のメカニズムによるところが大きかったりします。具体的には何が原因なのか、これから見ていきましょう。</p>

<ul>
<li><a href="https://html5experts.jp/furoshiki/6299/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Navigation Timingだからできる、Webアプリを俯瞰したパフォーマンス計測(2/3)</a></li>
<li><a href="https://html5experts.jp/furoshiki/6335/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Navigation Timingだからできる、Webアプリを俯瞰したパフォーマンス計測(3/3)</a></li>
</ul>

<p><em>※ 修正 2014.5.11：<a href="https://html5experts.jp/myakura/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">矢倉 眞隆</a>さんからのご指摘により、サンプルのwindow.performanceのベンダプレフィクスは削除しました。IE9+を含む近年のブラウザでは、3年近く前にベンダプレフィクスが消えており、無意味であると判断できたためです。</em></p>
]]></content:encoded>
		
		<series:name><![CDATA[パフォーマンスチューニング]]></series:name>
	</item>
	</channel>
</rss>
