C#でMemoryCacheクラスを試す。

C# コンピュータ
C#
コンピュータ関連でキャッシュ機能といいますと、読み込んだデータを次に利用するためにメモリーなど高速な記憶装置に保存しておき、同じデータが必要な場合キャッシュから取り出すことで、パフォーマンスを向上させる仕組みのことだと思われます。

dictionary<string, T>あたりを使って似たような機能を持たせたことがありますが、使用するメモリーの上限設定やキャッシュデータの解放条件、あとマルチスレッド時の排他処理など、しっかりプログラミングしようと思うと結構大変です。
MemoryCacheが利用できるのであれば、プログラミング的に楽が出来そうなので試してみたいと思います。

プロジェクトの作成

PowerShellで実行。要dotnet.exe

mkdir MemoryCacheSample
cd MemoryCacheSample
dotnet new console
dotnet add package System.Runtime.Caching
code .

ソースコード

ファイル名:Program.cs

using System;
using System.Runtime.Caching;

namespace MemoryCacheSample
{
    class Program
    {
        static void Main()
        {
            var cache = MemoryCache.Default;

            var policy = new CacheItemPolicy
            {
                SlidingExpiration = new TimeSpan(0, 0, 3),  // 有効期限を3秒間にセット
                RemovedCallback = arg =>
                {
                    Console.WriteLine("key:{0}が削除された。", arg.CacheItem.Key);
                },
            };

            string key = "a";
            string result = "";

            // キャッシュにデータ無い場合
            if (cache[key] == null)
            {
                // データを取得(生成)しキャッシュにセット
                string setValue = "1";
                cache.Set(key, setValue, policy);
            }
            // キャッシュからデータを取得しキャスト
            result = cache[key] as string;

            Console.WriteLine("key:{0}, value:{1}", key, result);
            // key:a, value:1

            // 20秒待つ
            System.Threading.Thread.Sleep(20000);
            // key:aが削除された。<= 有効期限切れ

            // 追加
            cache.Add("b", "2", policy);
            cache.Add("c", "3", policy);
            cache.Add("d", "4", policy);

            // キャッシュに使用できる物理メモリの量をバイト単位で取得
            Console.WriteLine("CacheMemoryLimit:{0}GB", cache.CacheMemoryLimit / 1024 / 1024 / 1024);
            // CacheMemoryLimit:4GB

            // キャッシュに使える物理メモリの割合
            Console.WriteLine("PhysicalMemoryLimit:{0}%", cache.PhysicalMemoryLimit);
            // PhysicalMemoryLimit:99%


            // キャッシュアイテムのエントリ数
            Console.WriteLine("GetCount():{0}", cache.GetCount());
            // GetCount():2

            // キャッシュアイテムの削除
            cache.Remove("d");
            // key:dが削除された。

            // キャッシュの全てのエントリを解放
            cache.Dispose();
            //key:bが削除された。
            //key:cが削除された。
        }
    }
}

実行

dotnet run

感想

MemoryCacheのインスタンスにkeyとvalueのペアでデータをキャッシュします。キャッシュするデータ型はObject型ですので、キャストで本来の型に戻して使うようです。キャッシュの解放は最後の参照からの時間で解放する条件が使いやすそうです。

サンプルではSleepで意図的に有効期限切れを発生させてみましたが、Removeメソッドで特定のキャッシュエントリの解放やDisposeですべてのキャッシュエントリの解放など、プログラマが解放のタイミングをコントロールすることも出来るようです。
また、解放時に実行するコールバック関数を設定できることも確認できました。

キャッシュのメモリー管理については物理メモリのプロパティとキャッシュに使える割合のプロパティを見てみました。テストはしていませんが、こちらのプロパティ値の範囲内でやりくりしてくれることを期待します。

追記:20230519
ローカルPCで実行するアプリケーションに組み込もうと思い試してみましたが、基本的にASPなどで使うものみたいです。

コメント