Bug 1896607 - FOG: Memory reporter on the Rust side. r=chutten

This sets up the scaffolding on the Rust side and calls that from the
C++ side.
To start it only measures the size of pings.

This requires a Glean update that implements all that malloc_size_of.

Differential Revision: https://phabricator.services.mozilla.com/D210288
This commit is contained in:
Jan-Erik Rediger
2025-05-02 09:24:06 +00:00
committed by jrediger@mozilla.com
parent 9888dfdbf9
commit 9c8e0c6df6
7 changed files with 92 additions and 1 deletions

2
Cargo.lock generated
View File

@@ -1967,6 +1967,7 @@ dependencies = [
"inherent", "inherent",
"log", "log",
"mozbuild", "mozbuild",
"nserror",
"nsstring", "nsstring",
"once_cell", "once_cell",
"serde", "serde",
@@ -1975,6 +1976,7 @@ dependencies = [
"thin-vec", "thin-vec",
"time 0.1.45", "time 0.1.45",
"uuid", "uuid",
"wr_malloc_size_of",
"xpcom", "xpcom",
] ]

View File

@@ -22,6 +22,8 @@ xpcom = { path = "../../../../xpcom/rust/xpcom", optional = true }
thin-vec = { version = "0.2.1", features = ["gecko-ffi"] } thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
mozbuild = "0.1" mozbuild = "0.1"
serde_json = "1" serde_json = "1"
nserror = { path = "../../../../xpcom/rust/nserror" }
malloc_size_of = { path = "../../../../gfx/wr/wr_malloc_size_of", package = "wr_malloc_size_of", features = ["once_cell"] }
# Note, we will want to remove this when Bug 1925313 is fixed # Note, we will want to remove this when Bug 1925313 is fixed
[dependencies.time] [dependencies.time]

View File

@@ -25,3 +25,58 @@ pub mod ipc;
#[cfg(test)] #[cfg(test)]
mod common_test; mod common_test;
#[cfg(feature = "with_gecko")]
use nserror::{NS_ERROR_UNEXPECTED, NS_OK};
#[cfg(feature = "with_gecko")]
use nsstring::{nsACString, nsCStr};
#[cfg(feature = "with_gecko")]
use xpcom::interfaces::{nsIHandleReportCallback, nsIMemoryReporter, nsISupports};
#[cfg(feature = "with_gecko")]
use xpcom::RefPtr;
/// Collect a memory report for heap memory in bytes.
#[cfg(feature = "with_gecko")]
macro_rules! moz_collect_report {
($cb:ident, $path:expr, $amount:expr, $desc:expr, $data:expr) => {
$cb.Callback(
&nsCStr::new() as &nsACString,
&nsCStr::from($path) as &nsACString,
nsIMemoryReporter::KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES,
$amount as i64,
&nsCStr::from($desc) as &nsACString,
$data,
)
};
}
#[cfg(feature = "with_gecko")]
#[no_mangle]
unsafe extern "C" fn fog_collect_reports(
callback: *const nsIHandleReportCallback,
data: *const nsISupports,
_anonymize: bool,
) -> nserror::nsresult {
let callback = match RefPtr::from_raw(callback) {
Some(ptr) => ptr,
None => return NS_ERROR_UNEXPECTED,
};
extern "C" {
fn fog_malloc_size_of(ptr: *const xpcom::reexports::libc::c_void) -> usize;
}
let mut ops = malloc_size_of::MallocSizeOfOps::new(fog_malloc_size_of, None);
let ping_size = pings::fog_ping_alloc_size(&mut ops);
moz_collect_report!(
callback,
"explicit/fog/pings",
ping_size,
"Memory used by all FOG pings",
data
);
NS_OK
}

View File

@@ -18,6 +18,15 @@ pub enum Ping {
Child, Child,
} }
impl malloc_size_of::MallocSizeOf for Ping {
fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
match self {
Ping::Child => 0,
Ping::Parent { inner, .. } => inner.size_of(ops),
}
}
}
impl Ping { impl Ping {
/// Create a new ping type for the given name, whether to include the client ID and whether to /// Create a new ping type for the given name, whether to include the client ID and whether to
/// send this ping empty. /// send this ping empty.

View File

@@ -125,3 +125,15 @@ pub(crate) fn set_ping_enabled_by_id(id: u32, enabled: bool) {
} }
} }
} }
/// Measure the allocation size of all known pings.
#[doc(hidden)]
pub fn fog_ping_alloc_size(ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
use malloc_size_of::MallocSizeOf;
let mut n = 0;
{% for obj in all_objs['pings'].values() %}
n += ::once_cell::sync::Lazy::get(&{{ obj.name|snake_case }}).map(|p| p.size_of(ops)).unwrap_or(0);
{% endfor %}
n
}

View File

@@ -14,7 +14,7 @@ line_length = 100
tab_width = 2 tab_width = 2
language = "C++" language = "C++"
namespaces = ["mozilla::glean::impl"] namespaces = ["mozilla::glean::impl"]
includes = ["nsTArray.h", "nsString.h"] includes = ["nsTArray.h", "nsString.h", "nsIMemoryReporter.h"]
[export.rename] [export.rename]
"ThinVec" = "nsTArray" "ThinVec" = "nsTArray"

View File

@@ -655,6 +655,16 @@ void FOG::InitMemoryReporter() { RegisterWeakMemoryReporter(this); }
MOZ_DEFINE_MALLOC_SIZE_OF(FOGMallocSizeOf) MOZ_DEFINE_MALLOC_SIZE_OF(FOGMallocSizeOf)
// Rust doesn't support weak-linking, so MFBT_API functions like
// moz_malloc_size_of need a C++ wrapper that uses the regular ABI
//
// We're not using MOZ_DEFINE_MALLOC_SIZE_OF here because that makes the
// function `static`, which would make it not visible outside this file
extern "C" size_t fog_malloc_size_of(const void* aPtr) {
MOZ_REPORT(aPtr);
return moz_malloc_size_of(aPtr);
}
NS_IMETHODIMP NS_IMETHODIMP
FOG::CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData, FOG::CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
bool aAnonymize) { bool aAnonymize) {
@@ -663,6 +673,7 @@ FOG::CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
MOZ_COLLECT_REPORT("explicit/fog/impl", KIND_HEAP, UNITS_BYTES, MOZ_COLLECT_REPORT("explicit/fog/impl", KIND_HEAP, UNITS_BYTES,
aMallocSizeOf(this), aMallocSizeOf(this),
"Memory used by the FOG core implementation"); "Memory used by the FOG core implementation");
glean::impl::fog_collect_reports(aHandleReport, aData, aAnonymize);
return NS_OK; return NS_OK;
} }