Commit dcda564f authored by Paul Bone's avatar Paul Bone
Browse files

Bug 1822451 - Add about:memory entries for PHC r=glandium

Differential Revision: https://phabricator.services.mozilla.com/D173099

Depends on D173098
parent 845ba685
Loading
Loading
Loading
Loading
+22 −2
Original line number Diff line number Diff line
@@ -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.
@@ -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; }
@@ -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.
@@ -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

+35 −3
Original line number Diff line number Diff line
@@ -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.
@@ -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) {
@@ -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);
@@ -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;
}
@@ -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
+3 −0
Original line number Diff line number Diff line
@@ -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"
+19 −0
Original line number Diff line number Diff line
@@ -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;