アプリケーションが消費しているアドレス空間の量を調べてユーザーに報告するにはどうすればよいですか?
-
01-07-2019 - |
質問
私は 20 人以上のプログラマーからなるチームの一員として、アプリケーションのメモリ マネージャーを作成しています。メモリ クォータが不足しており、約 700 MB しか使用していないように見えるため、何が起こっているかを確認する必要があります。断片化など、すべてがどこへ向かうのかを報告できる必要があります。何か案は?
解決
これには既存のメモリ デバッグ ツールを使用できます。Memory Validator を見つけました。 1 非常に便利で、API レベル (ヒープ、新規...) と OS レベル (仮想メモリ) の両方の割り当てを追跡し、仮想メモリ マップを表示できます。
私が非常に便利だと感じたもう 1 つのオプションは、VirtualQuery 関数に基づいて仮想空間全体のマップをダンプできることです。このための私のコードは次のようになります。
void PrintVMMap()
{
size_t start = 0;
// TODO: make portable - not compatible with /3GB, 64b OS or 64b app
size_t end = 1U<<31; // map 32b user space only - kernel space not accessible
SYSTEM_INFO si;
GetSystemInfo(&si);
size_t pageSize = si.dwPageSize;
size_t longestFreeApp = 0;
int index=0;
for (size_t addr = start; addr<end; )
{
MEMORY_BASIC_INFORMATION buffer;
SIZE_T retSize = VirtualQuery((void *)addr,&buffer,sizeof(buffer));
if (retSize==sizeof(buffer) && buffer.RegionSize>0)
{
// dump information about this region
printf(.... some buffer information here ....);
// track longest feee region - usefull fragmentation indicator
if (buffer.State&MEM_FREE)
{
if (buffer.RegionSize>longestFreeApp) longestFreeApp = buffer.RegionSize;
}
addr += buffer.RegionSize;
index+= buffer.RegionSize/pageSize;
}
else
{
// always proceed
addr += pageSize;
index++;
}
}
printf("Longest free VM region: %d",longestFreeApp);
}
他のヒント
ツール ヘルプ API から、Heap32ListFirst/Heap32ListNext を使用してプロセス内のヒープに関する情報を確認したり、Module32First/Module32Next を使用してロードされたモジュールに関する情報を確認したりすることもできます。
「ツール ヘルプ」は Windows 9x で誕生しました。Windows NT 上の元のプロセス情報 API は PSAPI で、ツール ヘルプと部分的に (完全ではなく) 重複する機能を提供します。
私たちの (巨大な) アプリケーション (Win32 ゲーム) が最近「クォータが足りません」という例外をスローし始めたので、すべてのメモリがどこに行っているのかを突き止める必要がありました。それは簡単な仕事ではありません - この質問と これです それを知るための私の最初の試みでした。ヒープの動作は予期せぬものであり、使用したクォータの量と使用可能なクォータの量を正確に追跡することは、これまでのところ不可能であることが判明しています。実際のところ、いずれにせよ、これは特に有用な情報ではありません。「割り当て」と「物を置く場所」は微妙に、そして迷惑なほど異なる概念です。受け入れられた答えはこれ以上ないほど優れていますが、ヒープとモジュールを列挙することも便利です。私が使用した デバッグ診断 MS から、状況の真の恐ろしさを目の当たりにし、実際にすべてを徹底的に追跡することがいかに難しいかを理解してもらいました。