web-dev-qa-db-ja.com

MemoryCacheスコープセッションまたはアプリケーション全体ですか?

ASP.NETでMemoryCacheを使用していますが、うまく機能しています。リポジトリからのデータの新たなプルを防ぐために1時間キャッシュされるオブジェクトがあります。

キャッシングがデバッグで機能しているのを見ることができますが、最初の呼び出しが行われ、オブジェクトがキャッシュされた後、サーバーにデプロイされると、その後の呼び出しは約1/5の時間になります。

ただし、各newクライアントコール(まだその1時間ウィンドウ内-実際には1分または2分後)が私のサービス(キャッシュを行っている)への最初のコールを持っているように見えることに気付いていますデータがキャッシュされる前の元の呼び出しとほぼ同じ時間がかかります。

これは私が疑問に思うようになりました-MemoryCacheセッション固有であり、呼び出しを行う各新しいクライアントはそれ自身のキャッシュを保存している、または他の何かが最初の呼び出しに非常に長い時間がかかりますafterデータがキャッシュされたことを知っていますか?

45
atconway

[〜#〜] msdn [〜#〜] から:

CacheクラスとMemoryCacheクラスの主な違いは、ASP.NETアプリケーションではない.NET Frameworkアプリケーションで使用できるようにMemoryCacheクラスが変更されていることです。たとえば、MemoryCacheクラスはSystem.Webアセンブリに依存しません。別の違いは、同じアプリケーションおよび同じAppDomainインスタンスで使用するために、MemoryCacheクラスの複数のインスタンスを作成できることです。

それを読んで、反映されたコードで調査を行うと、MemoryCacheが単なるクラスであることは明らかです。 _MemoryCache.Default_プロパティを使用して同じインスタンスを(再)使用したり、必要な数のインスタンスを構築したりできます(ただし、推奨される数はできるだけ少なくします)。

基本的に答えはあなたのコードにあります。
_MemoryCache.Default_を使用すると、アプリケーションプールが存続する限りキャッシュが存続します。 (既定のアプリケーションプールのアイドルタイムアウトは20分で、1時間未満であることを思い出してください。)

new MemoryCache(string, NameValueCollection)を使用して作成する場合、上記の考慮事項に加えて、インスタンスを作成するコンテキストが適用されます。つまり、コントローラー内にインスタンスを作成する場合(そうでない場合)、キャッシュは存続します1つのリクエスト

参照が見つからないのは残念ですが、... MemoryCacheは、指定したキャッシュポリシーに従ってデータを保持することを保証しません。特に、アプリを実行しているマシンがメモリに負荷をかけると、キャッシュが破棄される可能性があります。

キャッシュ項目が早期に無効化される理由がまだわからない場合は、 RemoveCallback を利用して、アイテムの無効化の理由を調査できます。

70
Ramunas

これを1年後に確認すると、元の投稿でキャッシュがランダムに「ドロップ」することについて、さらに多くの情報が見つかりました。 MSDNは、構成可能なキャッシュプロパティCacheMemoryLimitMegabytesおよびPhysicalMemoryLimitPercentageについて次のように述べています。

デフォルト値は0です。つまり、MemoryCacheクラスの自動サイズヒューリスティックがデフォルトで使用されます。

いくつかの逆コンパイルと調査を行うと、CacheMemoryMonitor.csメモリのしきい値を定義するクラス。 AutoPrivateBytesLimitプロパティに関するそのクラスのコメントのサンプルを次に示します。

// Auto-generate the private bytes limit:
// - On 64bit, the auto value is MIN(60% physical_ram, 1 TB)
// - On x86, for 2GB, the auto value is MIN(60% physical_ram, 800 MB)
// - On x86, for 3GB, the auto value is MIN(60% physical_ram, 1800 MB)
//
// - If it's not a hosted environment (e.g. console app), the 60% in the above
//   formulas will become 100% because in un-hosted environment we don't launch
//   other processes such as compiler, etc.

specific値がキャッシュがよく使用される理由を理解するのと同じくらい重要であるとは限りません:largeオブジェクトを保存する何度もフェッチしたくない。これらのlargeオブジェクトがキャッシュに保存されており、これらの内部計算に基づくホスティング環境のメモリしきい値を超えている場合、キャッシュからアイテムを削除することができます自動的に。 IISで複数のアプリを実行する2 GBのメモリを備えたホストサーバーのメモリに非常に大きなコレクションを格納していたため、これは確かに私のOPを説明できます。

これらの値の設定には明示的なオーバーライドがあります。構成を介して(またはMemoryCacheインスタンスをセットアップするときに)CacheMemoryLimitMegabytesおよびPhysicalMemoryLimitPercentage値を設定できます。以下は、次のサンプルを修正したものです [〜#〜] msdn [〜#〜] リンクphysicalMemoryPercentageを95(%)に設定します:

<configuration>
  <system.runtime.caching>
    <memoryCache>
      <namedCaches>
          <add name="default" 
               physicalMemoryLimitPercentage="95" />
      </namedCaches>
    </memoryCache>
  </system.runtime.caching>
</configuration>
29
atconway