void TrackListMemoryUsage(FILE * fp) { // If there are no allocated blocks, then return now. size_t numBlocks = BlockHeader::CountBlocks(); if (numBlocks == 0) return; // Get an array of pointers to all extant blocks. BlockHeader **ppBlockHeader = (BlockHeader **)calloc(numBlocks, sizeof(*ppBlockHeader)); BlockHeader::GetBlocks(ppBlockHeader); // Sort the blocks by type name. std::sort( ppBlockHeader, ppBlockHeader + numBlocks, BlockHeader::TypeGreaterThan ); // Find out how many unique types we have. size_t numUniqueTypes = 1; for (size_t i = 1; i < numBlocks; i++) { char const *prevTypeName = ppBlockHeader[i - 1]->GetTypeName(); char const *currTypeName = ppBlockHeader[i]->GetTypeName(); if (strcmp(prevTypeName, currTypeName) != 0) numUniqueTypes++; } // Create an array of "digests" summarizing memory usage by type. size_t startPost = 0; size_t uniqueTypeIndex = 0; MemDigest *pMemDigestArray = (MemDigest *)calloc(numUniqueTypes, sizeof(*pMemDigestArray)); for (size_t i = 1; i <= numBlocks; i++) // yes, less than or *equal* to { char const *prevTypeName = ppBlockHeader[i - 1]->GetTypeName(); char const *currTypeName = (i < numBlocks) ? ppBlockHeader[i]->GetTypeName() : ""; if (strcmp(prevTypeName, currTypeName) != 0) { size_t endPost = i; SummarizeMemoryUsageForType( pMemDigestArray + uniqueTypeIndex, ppBlockHeader, startPost, endPost ); startPost = endPost; uniqueTypeIndex++; } } assert(uniqueTypeIndex = numUniqueTypes); // Sort the digests by total memory usage. std::sort( pMemDigestArray, pMemDigestArray + numUniqueTypes, MemDigest::TotalSizeGreaterThan ); // Compute the grand total memory usage. size_t grandTotalNumBlocks = 0; size_t grandTotalSize = 0; for (size_t i = 0; i < numUniqueTypes; i++) { grandTotalNumBlocks += pMemDigestArray[i].blockCount; grandTotalSize += pMemDigestArray[i].totalSize; } // Dump the memory usage statistics. fprintf(fp, "\n"); fprintf(fp, "-----------------------\n"); fprintf(fp, "Memory Usage Statistics\n"); fprintf(fp, "-----------------------\n"); fprintf(fp, "\n"); fprintf(fp, "%-50s%5s %5s %7s %s \n", "allocated type", "blocks", "", "bytes", ""); fprintf(fp, "%-50s%5s %5s %7s %s \n", "--------------", "------", "", "-----", ""); for (size_t i = 0; i < numUniqueTypes; i++) { MemDigest *pMD = pMemDigestArray + i; size_t blockCount = pMD->blockCount; double blockCountPct = 100.0 * blockCount / grandTotalNumBlocks; size_t totalSize = pMD->totalSize; double totalSizePct = 100.0 * totalSize / grandTotalSize; fprintf(fp, "%-50s %5d %5.1f%% %7d %5.1f%%\n", pMD->typeName, blockCount, blockCountPct, totalSize, totalSizePct ); } fprintf(fp, "%-50s %5s %5s %7s %s \n", "--------", "-----", "", "-------", ""); fprintf(fp, "%-50s %5d %5s %7d %s \n", "[totals]", grandTotalNumBlocks, "", grandTotalSize, ""); // Clean up. free(ppBlockHeader); free(pMemDigestArray); }
size_t TotalBytesUsed() { // If there are no allocated blocks, then return now. size_t numBlocks = BlockHeader::CountBlocks(); if (numBlocks == 0) return 0; // Get an array of pointers to all extant blocks. BlockHeader **ppBlockHeader = (BlockHeader **)calloc(numBlocks, sizeof(*ppBlockHeader)); BlockHeader::GetBlocks(ppBlockHeader); // Sort the blocks by type name. std::sort( ppBlockHeader, ppBlockHeader + numBlocks, BlockHeader::TypeGreaterThan ); // Find out how many unique types we have. size_t numUniqueTypes = 1; for (size_t i = 1; i < numBlocks; i++) { char const *prevTypeName = ppBlockHeader[i - 1]->GetTypeName(); char const *currTypeName = ppBlockHeader[i]->GetTypeName(); if (strcmp(prevTypeName, currTypeName) != 0) numUniqueTypes++; } // Create an array of "digests" summarizing memory usage by type. size_t startPost = 0; size_t uniqueTypeIndex = 0; MemDigest *pMemDigestArray = (MemDigest *)calloc(numUniqueTypes, sizeof(*pMemDigestArray)); for (size_t i = 1; i <= numBlocks; i++) // yes, less than or *equal* to { char const *prevTypeName = ppBlockHeader[i - 1]->GetTypeName(); char const *currTypeName = (i < numBlocks) ? ppBlockHeader[i]->GetTypeName() : ""; if (strcmp(prevTypeName, currTypeName) != 0) { size_t endPost = i; SummarizeMemoryUsageForType( pMemDigestArray + uniqueTypeIndex, ppBlockHeader, startPost, endPost ); startPost = endPost; uniqueTypeIndex++; } } assert(uniqueTypeIndex = numUniqueTypes); // Sort the digests by total memory usage. std::sort( pMemDigestArray, pMemDigestArray + numUniqueTypes, MemDigest::TotalSizeGreaterThan ); // Compute the grand total memory usage. size_t grandTotalNumBlocks = 0; size_t grandTotalSize = 0; for (size_t i = 0; i < numUniqueTypes; i++) { grandTotalNumBlocks += pMemDigestArray[i].blockCount; grandTotalSize += pMemDigestArray[i].totalSize; } // Clean up. free(ppBlockHeader); free(pMemDigestArray); return grandTotalSize; }