mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-07 15:59:32 +03:00
Adding Anomaly Detection
This commit is contained in:
parent
3deac1bc60
commit
adfbdac7ec
2 changed files with 54 additions and 4 deletions
|
@ -43,6 +43,8 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arenas(PDEBUG_CLIENT c
|
||||||
size_t totalCommittedPages = 0;
|
size_t totalCommittedPages = 0;
|
||||||
size_t totalAbandonedPages = 0;
|
size_t totalAbandonedPages = 0;
|
||||||
|
|
||||||
|
std::vector<float> potentialFragmentation;
|
||||||
|
std::vector<float> highAbandonedPagesRatio;
|
||||||
for (size_t i = 0; i < arenaCount; ++i) {
|
for (size_t i = 0; i < arenaCount; ++i) {
|
||||||
ULONG64 arenaAddr = subprocMainAddr + offsetof(mi_subproc_t, arenas) + (i * sizeof(std::atomic<mi_arena_t*>));
|
ULONG64 arenaAddr = subprocMainAddr + offsetof(mi_subproc_t, arenas) + (i * sizeof(std::atomic<mi_arena_t*>));
|
||||||
ULONG64 arenaValueAddr = 0;
|
ULONG64 arenaValueAddr = 0;
|
||||||
|
@ -83,6 +85,7 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arenas(PDEBUG_CLIENT c
|
||||||
totalCommittedPages += committedPages;
|
totalCommittedPages += committedPages;
|
||||||
|
|
||||||
// For abandoned pages, iterate over each bin (0 to MI_BIN_COUNT - 1).
|
// For abandoned pages, iterate over each bin (0 to MI_BIN_COUNT - 1).
|
||||||
|
size_t abandonedPages = 0;
|
||||||
for (int bin = 0; bin < MI_BIN_COUNT; bin++) {
|
for (int bin = 0; bin < MI_BIN_COUNT; bin++) {
|
||||||
ULONG64 itemAdr = reinterpret_cast<ULONG64>(arena.pages_abandoned[bin]);
|
ULONG64 itemAdr = reinterpret_cast<ULONG64>(arena.pages_abandoned[bin]);
|
||||||
mi_bitmap_t abandonedBmp {};
|
mi_bitmap_t abandonedBmp {};
|
||||||
|
@ -92,9 +95,21 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arenas(PDEBUG_CLIENT c
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t abandonedPages = mi_bitmap_count(&abandonedBmp);
|
abandonedPages = mi_bitmap_count(&abandonedBmp);
|
||||||
totalAbandonedPages += abandonedPages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
totalAbandonedPages += abandonedPages;
|
||||||
|
|
||||||
|
// --- Anomaly Detection ---
|
||||||
|
float pctCommittedSlices = (arena.slice_count > 0) ? (committed * 100.0 / arena.slice_count) : 0.0;
|
||||||
|
potentialFragmentation.push_back(pctCommittedSlices);
|
||||||
|
|
||||||
|
float abandonedPagesRatio = 0.0;
|
||||||
|
if (committedPages > 0 && abandonedPages > 0) {
|
||||||
|
abandonedPagesRatio = (abandonedPages * 100.0) / committedPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
highAbandonedPagesRatio.push_back(abandonedPagesRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\nTotal Arenas: %d\n", arenaCount);
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\nTotal Arenas: %d\n", arenaCount);
|
||||||
|
@ -111,6 +126,19 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arenas(PDEBUG_CLIENT c
|
||||||
for (size_t i = 0; i < arenaCount; ++i) {
|
for (size_t i = 0; i < arenaCount; ++i) {
|
||||||
ULONG64 arenaAddr = subprocMainAddr + offsetof(mi_subproc_t, arenas) + (i * sizeof(std::atomic<mi_arena_t*>));
|
ULONG64 arenaAddr = subprocMainAddr + offsetof(mi_subproc_t, arenas) + (i * sizeof(std::atomic<mi_arena_t*>));
|
||||||
PrintLink(arenaAddr, std::format("!mi_dump_arena 0x{:016X}", arenaAddr), std::format("Arena {}", i));
|
PrintLink(arenaAddr, std::format("!mi_dump_arena 0x{:016X}", arenaAddr), std::format("Arena {}", i));
|
||||||
|
|
||||||
|
if (potentialFragmentation[i] < MinCommittedSlicesPct) {
|
||||||
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, " Warning: Low committed slices percentage (%.2f%%). Potential fragmentation detected.\n", potentialFragmentation[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (highAbandonedPagesRatio[i] > MaxAbandonedPagesRatio) {
|
||||||
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, " Warning: High ratio of abandoned pages (%.2f%%). Possible memory leak or delayed decommitment.\n",
|
||||||
|
highAbandonedPagesRatio[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (potentialFragmentation[i] < MinCommittedSlicesPct || highAbandonedPagesRatio[i] > MaxAbandonedPagesRatio) {
|
||||||
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
||||||
|
@ -191,6 +219,7 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arena(PDEBUG_CLIENT cl
|
||||||
totalCommittedPages += committedPages;
|
totalCommittedPages += committedPages;
|
||||||
|
|
||||||
// For abandoned pages, iterate over each bin (0 to MI_BIN_COUNT - 1).
|
// For abandoned pages, iterate over each bin (0 to MI_BIN_COUNT - 1).
|
||||||
|
size_t abandonedPages = 0;
|
||||||
for (int bin = 0; bin < MI_BIN_COUNT; bin++) {
|
for (int bin = 0; bin < MI_BIN_COUNT; bin++) {
|
||||||
ULONG64 itemAdr = reinterpret_cast<ULONG64>(arena.pages_abandoned[bin]);
|
ULONG64 itemAdr = reinterpret_cast<ULONG64>(arena.pages_abandoned[bin]);
|
||||||
mi_bitmap_t abandonedBmp {};
|
mi_bitmap_t abandonedBmp {};
|
||||||
|
@ -200,10 +229,11 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arena(PDEBUG_CLIENT cl
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t abandonedPages = mi_bitmap_count(&abandonedBmp);
|
abandonedPages = mi_bitmap_count(&abandonedBmp);
|
||||||
totalAbandonedPages += abandonedPages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
totalAbandonedPages += abandonedPages;
|
||||||
|
|
||||||
// Summary that aids in detecting fragmentation or undercommitment.
|
// Summary that aids in detecting fragmentation or undercommitment.
|
||||||
double pctCommitted = (totalSlices > 0) ? (totalCommittedSlices * 100.0 / totalSlices) : 0.0;
|
double pctCommitted = (totalSlices > 0) ? (totalCommittedSlices * 100.0 / totalSlices) : 0.0;
|
||||||
const auto arenaStats = std::format(" Total Slices: {}\n Committed Slices: {} ({}%)", totalSlices, totalCommittedSlices, pctCommitted);
|
const auto arenaStats = std::format(" Total Slices: {}\n Committed Slices: {} ({}%)", totalSlices, totalCommittedSlices, pctCommitted);
|
||||||
|
@ -213,5 +243,22 @@ extern "C" __declspec(dllexport) HRESULT CALLBACK mi_dump_arena(PDEBUG_CLIENT cl
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\nAggregated Page Statistics:\n%s\n", pageStats.c_str());
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\nAggregated Page Statistics:\n%s\n", pageStats.c_str());
|
||||||
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
||||||
|
|
||||||
|
// --- Anomaly Detection ---
|
||||||
|
float pctCommittedSlices = (arena.slice_count > 0) ? (committed * 100.0 / arena.slice_count) : 0.0;
|
||||||
|
|
||||||
|
float abandonedPagesRatio = 0.0;
|
||||||
|
if (committedPages > 0 && abandonedPages > 0) {
|
||||||
|
abandonedPagesRatio = (abandonedPages * 100.0) / committedPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pctCommittedSlices < MinCommittedSlicesPct) {
|
||||||
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, " Warning: Low committed slices percentage (%.2f%%). Potential fragmentation detected.\n", pctCommittedSlices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abandonedPagesRatio > MaxAbandonedPagesRatio) {
|
||||||
|
g_DebugControl->Output(DEBUG_OUTPUT_ERROR, " Warning: High ratio of abandoned pages (%.2f%%). Possible memory leak or delayed decommitment.\n", abandonedPagesRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_DebugControl->Output(DEBUG_OUTPUT_NORMAL, "\n");
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,9 @@ extern IDebugControl4* g_DebugControl;
|
||||||
extern IDebugSymbols3* g_DebugSymbols;
|
extern IDebugSymbols3* g_DebugSymbols;
|
||||||
extern IDebugDataSpaces* g_DataSpaces;
|
extern IDebugDataSpaces* g_DataSpaces;
|
||||||
|
|
||||||
|
constexpr double MinCommittedSlicesPct = 60.0; // if below threshold, potential fragmentation.
|
||||||
|
constexpr double MaxAbandonedPagesRatio = 0.4; // If abandoned pages exceed 40% of committed pages.
|
||||||
|
|
||||||
HRESULT FindMimallocBase();
|
HRESULT FindMimallocBase();
|
||||||
HRESULT GetSymbolOffset(const char* symbolName, ULONG64& outOffset);
|
HRESULT GetSymbolOffset(const char* symbolName, ULONG64& outOffset);
|
||||||
HRESULT ReadMemory(const char* symbolName, void* outBuffer, size_t bufferSize);
|
HRESULT ReadMemory(const char* symbolName, void* outBuffer, size_t bufferSize);
|
||||||
|
|
Loading…
Add table
Reference in a new issue