74

名前空間を使用してアプリケーションにキャッシュ機能を追加しSystem.Runtime.Cachingたいと考えており、おそらく複数の場所や異なるコンテキストでキャッシュを使用したいと考えています。そのために、いくつかの MemoryCache インスタンスを使用したいと考えています。

ただし、MemoryCacheの複数のインスタンスを使用することはお勧めできません。

MemoryCache はシングルトンではありませんが、いくつかの MemoryCache インスタンスのみ、場合によっては 1 つのみ作成する必要があり、アイテムをキャッシュするコードはそれらのインスタンスを使用する必要があります。

複数の MemoryCache インスタンスはアプリケーションにどのように影響しますか? アプリケーションで複数のキャッシュを使用することは非常に一般的なシナリオであるように思われるため、これは奇妙に思えます。

編集:より具体的には、インスタンスごとにキャッシュを保持する必要があるクラスがあります。使用を避けてMemoryCache、別のキャッシュ ソリューションを探す必要がありますか? この状況での使用MemoryCacheは悪いと見なされますか? もしそうなら、それはなぜですか?

4

2 に答える 2

77

私も最近これを経験しました。インメモリ キャッシュがプロセス固有であることを考慮すると (Web サイトまたはネイティブ ビジネス アプリの複数のインスタンスや複数のサーバーで共有されない)、複数のMemoryCacheインスタンスを使用するメリットはありません。

メモリ キャッシュは、そのメモリ管理機能のために、単独で使用することを主な目的としています。パフォーマンス カウンター (多少のオーバーヘッドがあります) に加えて、MemoryCache は、割り当てられたメモリが不足したときに項目を期限切れにすることもできます。

キャッシュの現在のインスタンスが CacheMemoryLimit プロパティによって設定されたメモリの制限を超えた場合、キャッシュ実装はキャッシュ エントリを削除します。アプリケーション内の各キャッシュ インスタンスは、CacheMemoryLimit プロパティで指定されたメモリ量を使用できます。

from MemoryCache.CacheMemoryLimit プロパティ

MemoryCache のインスタンスを 1 つだけ使用することで、このメモリ管理をアプリケーション インスタンス全体に効率的に適用できます。アプリケーション全体で最も重要でないアイテムを期限切れにします。これにより、ハードウェアの能力を超えることなく、メモリを最大限に使用できます。1 つの MemoryCache のスコープを (クラスの 1 つのインスタンスなどに) 制限すると、アプリケーションのメモリを効果的に管理できなくなります (すべてを「見る」ことができないため)。これらのキャッシュのすべてが「ビジー」である場合、メモリの管理が難しくなり、効率が低下する可能性があります。

これは、専用サーバーの余裕がないアプリケーションでは特に注意が必要です。150 MB の RAM (一般的な安価な月額 10 ドルのホスティング) しか割り当てられていない共有サーバーでアプリを実行しているとします。これを超えることなく最大限に使用するには、キャッシュを利用する必要があります。このメモリ使用量を超えると、アプリ プールがリサイクルされ、アプリのメモリ キャッシュがすべて失われます。(一般的な安価なホスティングの慣行) 同じことが、社内の共有企業サーバーでホストされている非 Web アプリケーションにも当てはまります。同じように、そのマシンのすべてのメモリを占有しないように、また他の基幹業務アプリと平和的に共存するように言われます。

そのメモリ制限、アプリ プールのリサイクル、キャッシュの喪失は、Web アプリにとって一般的な「アキレス腱」です。アプリが最もビジー状態になると、メモリ割り当てを超過し、すべてのキャッシュ エントリが失われるため、最も頻繁にリセットされます。そのため、最初にキャッシュされるべきものを再フェッチする作業が最も多くなります。つまり、アプリは最大負荷でパフォーマンスを得るのではなく、実際にパフォーマンスを低下させます。

MemoryCache が System.Web.Caching.Cache 実装の非 Web 固有バージョンであることは知っていますが、これはキャッシュ実装の背後にあるロジックを示しています。ハードウェアを排他的に使用していない場合は、Web 以外のプロジェクトにも同じロジックを適用できます。キャッシュがマシンにページファイルのスワップを強制的に開始させる場合、キャッシュはディスク上のキャッシュよりも速くなくなることに注意してください。その制限が2GBか何かであっても、常にどこかに制限が必要です。

私の場合、これについて読んだ後、アプリで1つの「public static MemoryCache」を使用するように切り替え、キャッシュされたアイテムをキャッシュキーで分離しました。たとえば、インスタンスごとにキャッシュする場合は、「instance-{instanceId}-resourceName-{resourceId}」のようなキャッシュ キーを使用できます。キャッシュ エントリの名前間隔と考えてください。

それが役立つことを願っています!

于 2012-11-16T22:23:57.127 に答える
6

私もいくつか使っています。通常、1 種類につき 1 つです。

を見ると、イベントMemoryCacheにフックされAppDomain、パフォーマンス カウンターが維持されていることがわかります。複数のリソース (CPU、カウンター、メモリなど) を使用すると、リソースに関するオーバーヘッドが発生するのではないかと思います。

于 2012-08-23T19:44:56.063 に答える