いくつかのテクニックが完全なページキャッシュに匹敵するパフォーマンスを上げることがある。パフォーマンスの問題で完全に外部データベースを切り離したとき、単純にインターネット接続がどれだけ早いかという疑問になることがある。パフォーマンス問題から外部データベースを完全に切り離せる場合、しばしば単にインターネット接続をどうやって早くするかになる。残念ながら、ページの完全なキャッシュを不可能にする、単なるユーザーの名前などのちょっとした情報が存在する。ここで、部分キャッシュとして知られる技術の出番となる。
部分キャッシュは、よく“ドーナツキャッシュ(donut caching)”と“ドーナツの穴キャッシュ(donut hole caching)”の2つのカテゴリに分けられる。私たちは、ASP.NET Webフォームを使って違いを説明しよう。
ドーナツの穴キャッシュは、Webサイトのビットとピースをキャッシュしている。Webフォームでは、再利用可能なコンテンツが、コントロールを通じてユーザー固有のコンテンツから物理的に分離されているため、ページのリファクタリングが必要になる。一度行うと、個々のコントロールにキャッシュディレクティブを使用することができる。残念ながら、これはデザイナがページをレイアウトする方法を大幅に制限する。
ドーナツキャッシュは、あとで追記される特定の“穴”を除いて、ページ全体をキャッシュする。Webフォーム2.0以降では、これらの穴はsubstitutionブロックとして知られている。substitutionブロックは、ほかの完全にキャッシュされたページから除外する特別なコントロールとして実装されている。静的なコールバックは、実行時にブロックを埋めるために使用される。Scott Guthrie氏は、以下の例を提供している:
Shared Function LoginText(ByVal Context As HttpContext) As String Return "Hello " & Context.User.Identity.Name End Function
つい最近までASP.NET MVCは、部分キャッシュをサポートしていなかった。これを実現する最善の策は、キャッシュされたJSONか、ブラウザで再構築するやHTMLデータのキャッシュをリクエストするAJAX呼び出しを含むことである。1月にリリースされたMVC 3からは、親ビューから呼び出される子アクションの結果をキャッシュすることができるようになっている。Html.ActionやHtml.RenderActionを使った呼び出しで、Webフォームのコントロールレベルのキャッシュに似ている。これには、いくつかの部分的なビューキャッシュの制約が存在している。Paul Hiles氏は、次のように要約する:
- キャッシュプロファイルはサポートされていない
- web.configのキャッシュ無効は無視される
- 特に子アクションのために出力キャッシュアイテムを削除することが容易ではない
- カスタム出力キャッシュストアを使うと問題がある
厄介なのは、ドーナツキャッシュとsubstitutionブロックのサポートが完全に抜けていることである。現在のASP.NET MVC 4のロードマップにはないので、Paul氏はオープンソースプロジェクトでMvcDonutCachingを提供している。この拡張は、“アクションの引数をシリアル化し、引数を含むHTMLを返す”ActionFilterAttributeをベースにしている。
これは完全な解決策ではなく、正規表現を使って、前述のHTMLコメントを探すために、実行時にキャッシュされた出力を解析する。それが見つかると、関連付けられたHtml.Actionが呼び出され、コメントがユーザー固有のコンテンツに置き換えられる。
MvcDonutCachingは実際に、Webフォームのsubstitutionブロックよりも簡単に使えるように表示される。おそらくこれはすでにユーザー固有のコンテンツの子アクションに使われているため、部分キャッシュを有効にすることはメインビューのタグ付するぐらい簡単にexcludeFromParentCache属性を含むHtml.Actionの新しいオーバーロードに切り替える。