【技術ソリューション事例#1】[.NET MAUI]MemoryToolkitを使ったメモリーリーク検知

| 0

はじめに

.NET MAUIアプリを作る際に一番苦労するのは、メモリーリークの対応だと思います。ただし、Visual Studioにあるパフォーマンスプロファイラーが.NET MAUIのモバイルアプリで使えないなど、Android Studioのプロファイラーほど気楽には使うことはできません。

情けない話ですが、筆者はMemory Leaksの欄を読んでも、結局dmpまで行きつくことはできませんでした。

メモリーリークを検知する簡単な方法ですが、コントリビュータの方が作ったMemoryToolkitというツールをアプリに埋め込むのが手軽でしたので、ここでご紹介します。

MemoryToolkitをアプリに埋め込む

githubのREADMEのQuick Startに詳細がありますが、こちらでもご紹介します。

・右の[ソリューションエクスプローラー]の[プロジェクト]を右クリック=>[Nugetパッケージの管理]をクリックし、[Nugetパッケージマネージャー]を表示
・検索窓で”AdamE.MemoryToolkit.Maui”と入力して、表示されたライブラリをインストール

・CreateMauiApp()内に以下を記載

    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                });
// ここから
#if DEBUG
            builder.Logging.AddDebug();

            // Ensure UseLeakDetection is called after logging has been configured!
            builder.UseLeakDetection(collectionTarget =>
            {
                // This callback will run any time a leak is detected.
                Application.Current?.MainPage?.DisplayAlert("💦Leak Detected💦",
                    $"❗🧟❗{collectionTarget.Name} is a zombie!", "OK");
            });
#endif
// ここまで
            return builder.Build();

・検知したい各画面のxamlファイルに以下を記載MemoryToolkit.Mauiの参照とLeakMonitorBehavior.Cascade=”True”を追加

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SampleCollectionViewApp.ItemPage"
             xmlns:mtk="clr-namespace:MemoryToolkit.Maui;assembly=MemoryToolkit.Maui"
             mtk:LeakMonitorBehavior.Cascade="True">
    ...
</ContentPage>

・これで事前準備が完了

メモリーリークの検知

実際にメモリーリークを検知します。

Microsoft.Maui.Controls, Microsoft.Maui.Controls.Compatibilityの8.0.20では、iOSのモーダル表示され、元画面に戻ると必ずメモリーリークになるため、遷移する際は以下のようにモーダル表示を指定します。

await Navigation.PushModalAsync(new Modal());

モーダルを表示してからモーダルを閉じると、画面とログで以下のようなアラートが表示されます。

アプリのメモリ使用量を表示する

上記でメモリーリークの「する/しない」の検知はできました。次はこの検知アプリが本当に正しいか、裏取りもかねてアプリのメモリ使用量を画面に表示します。こちらもMemoryToolkitのサンプルアプリを参考にしています。

	public CollectionPage()
	{
        // 事前に動的にメモリー開放する
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        // 画面の初期化
        InitializeComponent();
        // メモリ使用量を取得してXAMLで定義したHeapLabelラベルに表示する
        int heapSize = (int)(GC.GetTotalMemory(false) / 1024d);
        HeapLabel.Text = $"Heap Size: {heapSize} KB";
        // 以下画面表示
        ・・・
    }

以下のように画面に表示できました。これで、画面遷移しても無限にメモリー使用量が増えなければ、成功です。