Bug 1223927 - Add resident-unique measurement to OS X. r=njn

This commit is contained in:
Eric Rahm
2015-11-11 14:07:30 -08:00
parent ba7ed44d18
commit ab458da07c

View File

@@ -420,7 +420,10 @@ ResidentFastDistinguishedAmount(int64_t* aN)
#elif defined(XP_MACOSX)
#include <mach/mach_init.h>
#include <mach/mach_vm.h>
#include <mach/shared_region.h>
#include <mach/task.h>
#include <sys/sysctl.h>
static bool
GetTaskBasicInfo(struct task_basic_info* aTi)
@@ -485,6 +488,124 @@ ResidentDistinguishedAmount(int64_t* aN)
return ResidentDistinguishedAmountHelper(aN, /* doPurge = */ true);
}
#define HAVE_RESIDENT_UNIQUE_REPORTER 1
static bool
InSharedRegion(mach_vm_address_t aAddr, cpu_type_t aType)
{
mach_vm_address_t base;
mach_vm_address_t size;
switch (aType) {
case CPU_TYPE_ARM:
base = SHARED_REGION_BASE_ARM;
size = SHARED_REGION_SIZE_ARM;
break;
case CPU_TYPE_I386:
base = SHARED_REGION_BASE_I386;
size = SHARED_REGION_SIZE_I386;
break;
case CPU_TYPE_X86_64:
base = SHARED_REGION_BASE_X86_64;
size = SHARED_REGION_SIZE_X86_64;
break;
default:
return false;
}
return base <= aAddr && aAddr < (base + size);
}
static nsresult
ResidentUniqueDistinguishedAmount(int64_t* aN)
{
if (!aN) {
return NS_ERROR_FAILURE;
}
cpu_type_t cpu_type;
size_t len = sizeof(cpu_type);
if (sysctlbyname("sysctl.proc_cputype", &cpu_type, &len, NULL, 0) != 0) {
return NS_ERROR_FAILURE;
}
// Roughly based on libtop_update_vm_regions in
// http://www.opensource.apple.com/source/top/top-100.1.2/libtop.c
size_t privatePages = 0;
mach_vm_size_t size = 0;
for (mach_vm_address_t addr = MACH_VM_MIN_ADDRESS; ; addr += size) {
vm_region_top_info_data_t info;
mach_msg_type_number_t infoCount = VM_REGION_TOP_INFO_COUNT;
mach_port_t objectName;
kern_return_t kr =
mach_vm_region(mach_task_self(), &addr, &size, VM_REGION_TOP_INFO,
reinterpret_cast<vm_region_info_t>(&info),
&infoCount, &objectName);
if (kr == KERN_INVALID_ADDRESS) {
// Done iterating VM regions.
break;
} else if (kr != KERN_SUCCESS) {
return NS_ERROR_FAILURE;
}
if (InSharedRegion(addr, cpu_type) && info.share_mode != SM_PRIVATE) {
continue;
}
switch (info.share_mode) {
case SM_LARGE_PAGE:
// NB: Large pages are not shareable and always resident.
case SM_PRIVATE:
privatePages += info.private_pages_resident;
privatePages += info.shared_pages_resident;
break;
case SM_COW:
privatePages += info.private_pages_resident;
if (info.ref_count == 1) {
// Treat copy-on-write pages as private if they only have one reference.
privatePages += info.shared_pages_resident;
}
break;
case SM_SHARED:
default:
break;
}
}
vm_size_t pageSize;
if (host_page_size(mach_host_self(), &pageSize) != KERN_SUCCESS) {
pageSize = PAGE_SIZE;
}
*aN = privatePages * pageSize;
return NS_OK;
}
class ResidentUniqueReporter final : public nsIMemoryReporter
{
~ResidentUniqueReporter() {}
public:
NS_DECL_ISUPPORTS
NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize) override
{
int64_t amount = 0;
nsresult rv = ResidentUniqueDistinguishedAmount(&amount);
NS_ENSURE_SUCCESS(rv, rv);
return MOZ_COLLECT_REPORT(
"resident-unique", KIND_OTHER, UNITS_BYTES, amount,
"Memory mapped by the process that is present in physical memory and not "
"shared with any other processes. This is also known as the process's unique "
"set size (USS). This is the amount of RAM we'd expect to be freed if we "
"closed this process.");
}
};
NS_IMPL_ISUPPORTS(ResidentUniqueReporter, nsIMemoryReporter)
#elif defined(XP_WIN)
#include <windows.h>