| 1722 | }; |
| 1723 | |
| 1724 | static void DumpMemoryBlockUtilizationLocked() { |
| 1725 | TFreeListGroup* wholeLists[N_SIZES]; |
| 1726 | for (int nSizeIdx = 0; nSizeIdx < N_SIZES; ++nSizeIdx) { |
| 1727 | wholeLists[nSizeIdx] = (TFreeListGroup*)globalFreeLists[nSizeIdx].GetWholeList(); |
| 1728 | } |
| 1729 | char* bfList = (char*)blockFreeList.GetWholeList(); |
| 1730 | |
| 1731 | DebugTraceMMgr("memory blocks utilisation stats:\n"); |
| 1732 | i64 nTotalAllocated = 0, nTotalFree = 0, nTotalBadPages = 0, nTotalPages = 0, nTotalUsed = 0, nTotalLocked = 0; |
| 1733 | i64 nTotalGroupBlocks = 0; |
| 1734 | char* entries; |
| 1735 | entries = (char*)SystemAlloc((N_CHUNK_SIZE / 4)); |
| 1736 | for (size_t k = 0; k < N_CHUNKS; ++k) { |
| 1737 | if (chunkSizeIdx[k] <= 0) { |
| 1738 | if (chunkSizeIdx[k] == -1) |
| 1739 | nTotalLocked += N_CHUNK_SIZE; |
| 1740 | continue; |
| 1741 | } |
| 1742 | i64 nSizeIdx = chunkSizeIdx[k]; |
| 1743 | i64 nSize = nSizeIdxToSize[nSizeIdx]; |
| 1744 | TChunkStats cs(k, nSize, entries); |
| 1745 | int nEntriesTotal = N_CHUNK_SIZE / nSize; |
| 1746 | memset(entries, 0, nEntriesTotal); |
| 1747 | for (TFreeListGroup* g = wholeLists[nSizeIdx]; g; g = g->Next) { |
| 1748 | for (auto ptr : g->Ptrs) |
| 1749 | cs.CheckBlock(ptr); |
| 1750 | } |
| 1751 | TChunkStats csGB(k, nSize, entries); |
| 1752 | if (nSizeIdx == FREE_LIST_GROUP_SIZEIDX) { |
| 1753 | for (auto g : wholeLists) { |
| 1754 | for (; g; g = g->Next) |
| 1755 | csGB.CheckBlock((char*)g); |
| 1756 | } |
| 1757 | for (char* blk = bfList; blk; blk = *(char**)blk) |
| 1758 | csGB.CheckBlock(blk); |
| 1759 | nTotalGroupBlocks += csGB.FreeCount * nSize; |
| 1760 | } |
| 1761 | if (((globalCurrentPtr[nSizeIdx] - ALLOC_START) / N_CHUNK_SIZE) == k) |
| 1762 | cs.SetGlobalFree(globalCurrentPtr[nSizeIdx]); |
| 1763 | nTotalUsed += (nEntriesTotal - cs.FreeCount - csGB.FreeCount) * nSize; |
| 1764 | |
| 1765 | char pages[N_CHUNK_SIZE / N_PAGE_SIZE]; |
| 1766 | memset(pages, 0, sizeof(pages)); |
| 1767 | for (int i = 0, nShift = 0; i < nEntriesTotal; ++i, nShift += nSize) { |
| 1768 | int nBit = 0; |
| 1769 | if (entries[i]) |
| 1770 | nBit = 1; // free entry |
| 1771 | else |
| 1772 | nBit = 2; // used entry |
| 1773 | for (i64 nDelta = nSize - 1; nDelta >= 0; nDelta -= N_PAGE_SIZE) |
| 1774 | pages[(nShift + nDelta) / N_PAGE_SIZE] |= nBit; |
| 1775 | } |
| 1776 | i64 nBadPages = 0; |
| 1777 | for (auto page : pages) { |
| 1778 | nBadPages += page == 3; |
| 1779 | nTotalPages += page != 1; |
| 1780 | } |
| 1781 | DebugTraceMMgr("entry = %lld; size = %lld; free = %lld; system %lld; utilisation = %g%%, fragmentation = %g%%\n", |
no test coverage detected