Loading memory/build/replace_malloc_bridge.h +22 −2 Original line number Diff line number Diff line Loading @@ -117,6 +117,16 @@ struct DMDFuncs; namespace phc { class AddrInfo; struct MemoryUsage { // The amount of memory used for PHC metadata, eg information about each // allocation including stacks. size_t mMetadataBytes = 0; // The amount of memory lost due to rounding allocation sizes up to the // nearest page. AKA internal fragmentation. size_t mFragmentationBytes = 0; }; } // namespace phc // Callbacks to register debug file handles for Poison IO interpose. Loading @@ -126,11 +136,10 @@ struct DebugFdRegistry { virtual void UnRegisterHandle(intptr_t aFd); }; } // namespace mozilla struct ReplaceMallocBridge { ReplaceMallocBridge() : mVersion(4) {} ReplaceMallocBridge() : mVersion(5) {} // This method was added in version 1 of the bridge. virtual mozilla::dmd::DMDFuncs* GetDMDFuncs() { return nullptr; } Loading Loading @@ -182,6 +191,10 @@ struct ReplaceMallocBridge { // This method was added in version 4 of the bridge. virtual bool IsPHCEnabledOnCurrentThread() { return false; } // Return PHC memory usage information by filling in the supplied structure. // This method was added in version 5 of the bridge. virtual void PHCMemoryUsage(mozilla::phc::MemoryUsage& aMemoryUsage) {} # ifndef REPLACE_MALLOC_IMPL // Returns the replace-malloc bridge if its version is at least the // requested one. Loading Loading @@ -249,6 +262,13 @@ struct ReplaceMalloc { auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 4); return singleton ? singleton->IsPHCEnabledOnCurrentThread() : false; } static void PHCMemoryUsage(mozilla::phc::MemoryUsage& aMemoryUsage) { auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 5); if (singleton) { singleton->PHCMemoryUsage(aMemoryUsage); } } }; # endif Loading memory/replace/phc/PHC.cpp +35 −3 Original line number Diff line number Diff line Loading @@ -656,6 +656,12 @@ class GMut { (kPageSize - 1)); } // The internal fragmentation for this allocation. size_t FragmentationBytes() const { MOZ_ASSERT(kPageSize >= UsableSize()); return mState == AllocPageState::InUse ? kPageSize - UsableSize() : 0; } // The allocation stack. // - NeverAllocated: Nothing. // - InUse | Freed: Some. Loading Loading @@ -719,6 +725,15 @@ class GMut { return page.UsableSize(); } // The total fragmentation in PHC size_t FragmentationBytes() const { size_t sum = 0; for (auto page : mAllocPages) { sum += page.FragmentationBytes(); } return sum; } void SetPageInUse(GMutLock aLock, uintptr_t aIndex, const Maybe<arena_id_t>& aArenaId, uint8_t* aBaseAddr, const StackTrace& aAllocStack) { Loading Loading @@ -1389,6 +1404,11 @@ static size_t replace_malloc_usable_size(usable_ptr_t aPtr) { return gMut->PageUsableSize(lock, index); } static size_t metadata_size() { return sMallocTable.malloc_usable_size(gConst) + sMallocTable.malloc_usable_size(gMut); } void replace_jemalloc_stats(jemalloc_stats_t* aStats, jemalloc_bin_stats_t* aBinStats) { sMallocTable.jemalloc_stats_internal(aStats, aBinStats); Loading Loading @@ -1419,10 +1439,11 @@ void replace_jemalloc_stats(jemalloc_stats_t* aStats, // aStats.page_cache and aStats.bin_unused are left unchanged because PHC // doesn't have anything corresponding to those. // gConst and gMut are normal heap allocations, so they're measured by // The metadata is stored in normal heap allocations, so they're measured by // mozjemalloc as `allocated`. Move them into `bookkeeping`. size_t bookkeeping = sMallocTable.malloc_usable_size(gConst) + sMallocTable.malloc_usable_size(gMut); // They're also reported under explicit/heap-overhead/phc/fragmentation in // about:memory. size_t bookkeeping = metadata_size(); aStats->allocated -= bookkeeping; aStats->bookkeeping += bookkeeping; } Loading Loading @@ -1554,6 +1575,17 @@ class PHCBridge : public ReplaceMallocBridge { LOG("IsPHCEnabledOnCurrentThread: %zu\n", size_t(enabled)); return enabled; } virtual void PHCMemoryUsage( mozilla::phc::MemoryUsage& aMemoryUsage) override { aMemoryUsage.mMetadataBytes = metadata_size(); if (gMut) { MutexAutoLock lock(GMut::sMutex); aMemoryUsage.mFragmentationBytes = gMut->FragmentationBytes(); } else { aMemoryUsage.mFragmentationBytes = 0; } } }; // WARNING: this function runs *very* early -- before all static initializers Loading xpcom/base/moz.build +3 −0 Original line number Diff line number Diff line Loading @@ -220,6 +220,9 @@ if CONFIG["OS_TARGET"] == "Linux": "AvailableMemoryWatcherUtils.h", ] if CONFIG["MOZ_PHC"]: DEFINES["MOZ_PHC"] = True GeneratedFile("ErrorList.h", script="ErrorList.py", entry_point="error_list_h") GeneratedFile( "ErrorNamesInternal.h", script="ErrorList.py", entry_point="error_names_internal_h" Loading xpcom/base/nsMemoryReporterManager.cpp +19 −0 Original line number Diff line number Diff line Loading @@ -1335,6 +1335,25 @@ class JemallocHeapReporter final : public nsIMemoryReporter { MOZ_COLLECT_REPORT( "heap-chunksize", KIND_OTHER, UNITS_BYTES, stats.chunksize, "Size of chunks."); #ifdef MOZ_PHC mozilla::phc::MemoryUsage usage; ReplaceMalloc::PHCMemoryUsage(usage); MOZ_COLLECT_REPORT( "explicit/heap-overhead/phc/metadata", KIND_NONHEAP, UNITS_BYTES, usage.mMetadataBytes, "Memory used by PHC to store stacks and other metadata for each allocation"); MOZ_COLLECT_REPORT( "explicit/heap-overhead/phc/fragmentation", KIND_NONHEAP, UNITS_BYTES, usage.mFragmentationBytes, "The amount of memory lost due to rounding up allocations to the next page " "size. " "This is also known as 'internal fragmentation'. " "Note that all allocators have some internal fragmentation, there may still " "be some internal fragmentation without PHC."); #endif // clang-format on return NS_OK; Loading Loading
memory/build/replace_malloc_bridge.h +22 −2 Original line number Diff line number Diff line Loading @@ -117,6 +117,16 @@ struct DMDFuncs; namespace phc { class AddrInfo; struct MemoryUsage { // The amount of memory used for PHC metadata, eg information about each // allocation including stacks. size_t mMetadataBytes = 0; // The amount of memory lost due to rounding allocation sizes up to the // nearest page. AKA internal fragmentation. size_t mFragmentationBytes = 0; }; } // namespace phc // Callbacks to register debug file handles for Poison IO interpose. Loading @@ -126,11 +136,10 @@ struct DebugFdRegistry { virtual void UnRegisterHandle(intptr_t aFd); }; } // namespace mozilla struct ReplaceMallocBridge { ReplaceMallocBridge() : mVersion(4) {} ReplaceMallocBridge() : mVersion(5) {} // This method was added in version 1 of the bridge. virtual mozilla::dmd::DMDFuncs* GetDMDFuncs() { return nullptr; } Loading Loading @@ -182,6 +191,10 @@ struct ReplaceMallocBridge { // This method was added in version 4 of the bridge. virtual bool IsPHCEnabledOnCurrentThread() { return false; } // Return PHC memory usage information by filling in the supplied structure. // This method was added in version 5 of the bridge. virtual void PHCMemoryUsage(mozilla::phc::MemoryUsage& aMemoryUsage) {} # ifndef REPLACE_MALLOC_IMPL // Returns the replace-malloc bridge if its version is at least the // requested one. Loading Loading @@ -249,6 +262,13 @@ struct ReplaceMalloc { auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 4); return singleton ? singleton->IsPHCEnabledOnCurrentThread() : false; } static void PHCMemoryUsage(mozilla::phc::MemoryUsage& aMemoryUsage) { auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 5); if (singleton) { singleton->PHCMemoryUsage(aMemoryUsage); } } }; # endif Loading
memory/replace/phc/PHC.cpp +35 −3 Original line number Diff line number Diff line Loading @@ -656,6 +656,12 @@ class GMut { (kPageSize - 1)); } // The internal fragmentation for this allocation. size_t FragmentationBytes() const { MOZ_ASSERT(kPageSize >= UsableSize()); return mState == AllocPageState::InUse ? kPageSize - UsableSize() : 0; } // The allocation stack. // - NeverAllocated: Nothing. // - InUse | Freed: Some. Loading Loading @@ -719,6 +725,15 @@ class GMut { return page.UsableSize(); } // The total fragmentation in PHC size_t FragmentationBytes() const { size_t sum = 0; for (auto page : mAllocPages) { sum += page.FragmentationBytes(); } return sum; } void SetPageInUse(GMutLock aLock, uintptr_t aIndex, const Maybe<arena_id_t>& aArenaId, uint8_t* aBaseAddr, const StackTrace& aAllocStack) { Loading Loading @@ -1389,6 +1404,11 @@ static size_t replace_malloc_usable_size(usable_ptr_t aPtr) { return gMut->PageUsableSize(lock, index); } static size_t metadata_size() { return sMallocTable.malloc_usable_size(gConst) + sMallocTable.malloc_usable_size(gMut); } void replace_jemalloc_stats(jemalloc_stats_t* aStats, jemalloc_bin_stats_t* aBinStats) { sMallocTable.jemalloc_stats_internal(aStats, aBinStats); Loading Loading @@ -1419,10 +1439,11 @@ void replace_jemalloc_stats(jemalloc_stats_t* aStats, // aStats.page_cache and aStats.bin_unused are left unchanged because PHC // doesn't have anything corresponding to those. // gConst and gMut are normal heap allocations, so they're measured by // The metadata is stored in normal heap allocations, so they're measured by // mozjemalloc as `allocated`. Move them into `bookkeeping`. size_t bookkeeping = sMallocTable.malloc_usable_size(gConst) + sMallocTable.malloc_usable_size(gMut); // They're also reported under explicit/heap-overhead/phc/fragmentation in // about:memory. size_t bookkeeping = metadata_size(); aStats->allocated -= bookkeeping; aStats->bookkeeping += bookkeeping; } Loading Loading @@ -1554,6 +1575,17 @@ class PHCBridge : public ReplaceMallocBridge { LOG("IsPHCEnabledOnCurrentThread: %zu\n", size_t(enabled)); return enabled; } virtual void PHCMemoryUsage( mozilla::phc::MemoryUsage& aMemoryUsage) override { aMemoryUsage.mMetadataBytes = metadata_size(); if (gMut) { MutexAutoLock lock(GMut::sMutex); aMemoryUsage.mFragmentationBytes = gMut->FragmentationBytes(); } else { aMemoryUsage.mFragmentationBytes = 0; } } }; // WARNING: this function runs *very* early -- before all static initializers Loading
xpcom/base/moz.build +3 −0 Original line number Diff line number Diff line Loading @@ -220,6 +220,9 @@ if CONFIG["OS_TARGET"] == "Linux": "AvailableMemoryWatcherUtils.h", ] if CONFIG["MOZ_PHC"]: DEFINES["MOZ_PHC"] = True GeneratedFile("ErrorList.h", script="ErrorList.py", entry_point="error_list_h") GeneratedFile( "ErrorNamesInternal.h", script="ErrorList.py", entry_point="error_names_internal_h" Loading
xpcom/base/nsMemoryReporterManager.cpp +19 −0 Original line number Diff line number Diff line Loading @@ -1335,6 +1335,25 @@ class JemallocHeapReporter final : public nsIMemoryReporter { MOZ_COLLECT_REPORT( "heap-chunksize", KIND_OTHER, UNITS_BYTES, stats.chunksize, "Size of chunks."); #ifdef MOZ_PHC mozilla::phc::MemoryUsage usage; ReplaceMalloc::PHCMemoryUsage(usage); MOZ_COLLECT_REPORT( "explicit/heap-overhead/phc/metadata", KIND_NONHEAP, UNITS_BYTES, usage.mMetadataBytes, "Memory used by PHC to store stacks and other metadata for each allocation"); MOZ_COLLECT_REPORT( "explicit/heap-overhead/phc/fragmentation", KIND_NONHEAP, UNITS_BYTES, usage.mFragmentationBytes, "The amount of memory lost due to rounding up allocations to the next page " "size. " "This is also known as 'internal fragmentation'. " "Note that all allocators have some internal fragmentation, there may still " "be some internal fragmentation without PHC."); #endif // clang-format on return NS_OK; Loading