Windowsパソコンの場合、アプリのメモリ使用量はタスクマネージャーで分かる。 いちいち、タスクマネージャーで確認するのが煩わしいので、アプリ画面の片隅に常時表示するか、 ヘルプメニューのクリックで確認できるようにしたい。
これまでのプログラムを真似てもよいが、なるべく簡単な方がいいので、改めてネット検索してみた。
記事[1]に色んな方法が紹介されている。このなかで、一番簡単そうな方法を試そう。
ロセスのメモリ使用量取得は、Environment.WorkingSetプロパティ、GCクラス、Processクラス のいずれでもプログラム的には大差がない。
日頃、ガーベージコレクションコレクションが気になっているので、GCクラスを使ってみる。
long currentSet = GC.GetTotalMemory(true); label.Text = string.Format("GC.GetTotalMemory={0}byte", currentSet.ToString("N0"));
地図システムでの使用は次のようにした。毎回、地図画面を書き換えたときに左下の下から2番目に その時点でのメモリ使用量をMB単位(小数点以下切り捨て)で表示する。
public class Map : Panel {
protected override void OnPaint(PaintEventArgs e) {
Graphics g = e.Graphics;
// 省略
Brush brush = new SolidBrush(Color.Black);
Font font = new Font("Meiryo UI", 10, FontStyle.Regular);
//long mem = GC.GetTotalMemory(true)/1024/1024;
long mem = Environment.WorkingSet/1024/1024;
g.DrawString(mem+"MB", font, brush, 2, H-35);
g.DrawString(zoom+"/"+(int)(CX/PX)+"/"+(int)(CY/PX), font, brush, 2, H-20);
}
}
実画面例を下に示す。これは開発途上のプログラムであり、地図にはまだ表示していないが、 最終的には表示するデータをすでにメモリに読込んでいるため、248MBという大きさになっている。
ところが、タスクマネージャーでは 388MB になっている。この大差の原因はまだ分からない。
アプリ起動後、1時間以上たってから確認するとタスクマネージャーでのメモリ使用量は わずか 45MB になっていた。アプリに読込んだ大半のデータは現時点では使っていないため、 PCが主記憶からスワップアウトしたのであろう。
起動直後は純粋にアプリが使う以上のデータがアサインされているのかも知れない。
OnPaintでの GC.GetTotalMemoryの実行は問題があることが分かった。
Environment.WorkingSet の場合、問題はない。数値はタスクマネージャーに近い値となった。 しかし、OnPaintで頻繁に実行するのはパフォーマンス上好ましくない。