Commit 52b7b6b6 authored by erikchen's avatar erikchen Committed by Commit Bot

Remove GetCommittedKBytes and GetWorkingSetKBytes.

There are no longer any cross-platform consumers of this code. There are two
ChromeOS consumers of the latter, which have been extracted into a function only
defined on ChromeOS.

Bug: 819289
Change-Id: Iaa0c12c94619ba54be44e23eb45abc5337da4621
Reviewed-on: https://chromium-review.googlesource.com/973943
Commit-Queue: Erik Chen <erikchen@chromium.org>
Reviewed-by: default avatarNick Carter <nick@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#545578}
parent 8478ca40
......@@ -41,58 +41,6 @@ namespace base {
// Full declaration is in process_metrics_iocounters.h.
struct IoCounters;
// Working Set (resident) memory usage broken down by
//
// On Windows:
// priv (private): These pages (kbytes) cannot be shared with any other process.
// shareable: These pages (kbytes) can be shared with other processes under
// the right circumstances.
// shared : These pages (kbytes) are currently shared with at least one
// other process.
//
// On Linux:
// priv: Pages mapped only by this process.
// shared: PSS or 0 if the kernel doesn't support this.
// shareable: 0
// On ChromeOS:
// priv: Pages mapped only by this process.
// shared: PSS or 0 if the kernel doesn't support this.
// shareable: 0
// swapped Pages swapped out to zram.
//
// On macOS:
// priv: Resident size (RSS) including shared memory. Warning: This
// does not include compressed size and does not always
// accurately account for shared memory due to things like
// copy-on-write. TODO(erikchen): Revamp this with something
// more accurate.
// shared: 0
// shareable: 0
//
struct WorkingSetKBytes {
WorkingSetKBytes() : priv(0), shareable(0), shared(0) {}
size_t priv;
size_t shareable;
size_t shared;
#if defined(OS_CHROMEOS)
size_t swapped;
#endif
};
// Committed (resident + paged) memory usage broken down by
// private: These pages cannot be shared with any other process.
// mapped: These pages are mapped into the view of a section (backed by
// pagefile.sys)
// image: These pages are mapped into the view of an image section (backed by
// file system)
struct CommittedKBytes {
CommittedKBytes() : priv(0), mapped(0), image(0) {}
size_t priv;
size_t mapped;
size_t image;
};
#if defined(OS_LINUX) || defined(OS_ANDROID)
// Minor and major page fault counts since the process creation.
// Both counts are process-wide, and exclude child processes.
......@@ -108,11 +56,20 @@ struct PageFaultCounts {
// Convert a POSIX timeval to microseconds.
BASE_EXPORT int64_t TimeValToMicroseconds(const struct timeval& tv);
// Provides performance metrics for a specified process (CPU usage, memory and
// IO counters). Use CreateCurrentProcessMetrics() to get an instance for the
// Provides performance metrics for a specified process (CPU usage and IO
// counters). Use CreateCurrentProcessMetrics() to get an instance for the
// current process, or CreateProcessMetrics() to get an instance for an
// arbitrary process. Then, access the information with the different get
// methods.
//
// This class exposes a few platform-specific APIs for parsing memory usage, but
// these are not intended to generalize to other platforms, since the memory
// models differ substantially.
//
// To obtain consistent memory metrics, use the memory_instrumentation service.
//
// For further documentation on memory, see
// https://chromium.googlesource.com/chromium/src/+/HEAD/docs/README.md
class BASE_EXPORT ProcessMetrics {
public:
~ProcessMetrics();
......@@ -135,27 +92,27 @@ class BASE_EXPORT ProcessMetrics {
// convenience wrapper for CreateProcessMetrics().
static std::unique_ptr<ProcessMetrics> CreateCurrentProcessMetrics();
// Fills a CommittedKBytes with both resident and paged
// memory usage as per definition of CommittedBytes.
void GetCommittedKBytes(CommittedKBytes* usage) const;
// Fills a WorkingSetKBytes containing resident private and shared memory
// usage in bytes, as per definition of WorkingSetBytes. Note that this
// function is somewhat expensive on Windows (a few ms per process).
bool GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const;
#if defined(OS_LINUX) || defined(OS_ANDROID)
// Resident Set Size is a Linux/Android specific memory concept. Do not
// attempt to extend this to other platforms.
BASE_EXPORT size_t GetResidentSetSize() const;
#endif
#if defined(OS_MACOSX)
// Fills both CommitedKBytes and WorkingSetKBytes in a single operation. This
// is more efficient on Mac OS X, as the two can be retrieved with a single
// system call.
bool GetCommittedAndWorkingSetKBytes(CommittedKBytes* usage,
WorkingSetKBytes* ws_usage) const;
#if defined(OS_CHROMEOS)
// /proc/<pid>/totmaps is a syscall that returns memory summary statistics for
// the process.
// totmaps is a Linux specific concept, currently only being used on ChromeOS.
// Do not attempt to extend this to other platforms.
//
struct TotalsSummary {
size_t private_clean_kb;
size_t private_dirty_kb;
size_t swap_kb;
};
BASE_EXPORT TotalsSummary GetTotalsSummary() const;
#endif
#if defined(OS_MACOSX)
struct TaskVMInfo {
// Only available on macOS 10.12+.
// Anonymous, non-discardable memory, including non-volatile IOKit.
......@@ -243,14 +200,6 @@ class BASE_EXPORT ProcessMetrics {
ProcessMetrics(ProcessHandle process, PortProvider* port_provider);
#endif // !defined(OS_MACOSX) || defined(OS_IOS)
#if defined(OS_LINUX) || defined(OS_ANDROID) | defined(OS_AIX)
bool GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage) const;
#endif
#if defined(OS_CHROMEOS)
bool GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage) const;
#endif
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
int CalculateIdleWakeupsPerSecond(uint64_t absolute_idle_wakeups);
#endif
......
......@@ -26,31 +26,6 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
return WrapUnique(new ProcessMetrics(process));
}
namespace {
size_t GetWorkingSetSize() {
struct kinfo_proc info;
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_ };
size_t length = sizeof(info);
if (sysctl(mib, arraysize(mib), &info, &length, NULL, 0) < 0)
return 0;
return info.ki_rssize * getpagesize();
}
} // namespace
bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
// TODO(bapt) be sure we can't be precise
size_t priv = GetWorkingSetSize();
if (!priv)
return false;
ws_usage->priv = priv / 1024;
ws_usage->shareable = 0;
ws_usage->shared = 0;
return true;
}
double ProcessMetrics::GetPlatformIndependentCPUUsage() {
struct kinfo_proc info;
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_ };
......
......@@ -30,11 +30,6 @@ double ProcessMetrics::GetPlatformIndependentCPUUsage() {
return 0.0;
}
bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
NOTIMPLEMENTED(); // TODO(fuchsia): https://crbug.com/706592.
return false;
}
bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
NOTIMPLEMENTED(); // TODO(fuchsia): https://crbug.com/706592.
return false;
......
......@@ -216,14 +216,6 @@ size_t ProcessMetrics::GetResidentSetSize() const {
getpagesize();
}
bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
#if defined(OS_CHROMEOS)
if (GetWorkingSetKBytesTotmaps(ws_usage))
return true;
#endif
return GetWorkingSetKBytesStatm(ws_usage);
}
double ProcessMetrics::GetPlatformIndependentCPUUsage() {
TimeTicks time = TimeTicks::Now();
......@@ -376,8 +368,7 @@ ProcessMetrics::ProcessMetrics(ProcessHandle process)
#if defined(OS_CHROMEOS)
// Private, Shared and Proportional working set sizes are obtained from
// /proc/<pid>/totmaps
bool ProcessMetrics::GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage)
const {
ProcessMetrics::TotalsSummary ProcessMetrics::GetTotalsSummary() const {
// The format of /proc/<pid>/totmaps is:
//
// Rss: 6120 kB
......@@ -391,7 +382,8 @@ bool ProcessMetrics::GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage)
// AnonHugePages: XXX kB
// Swap: XXX kB
// Locked: XXX kB
const size_t kPssIndex = (1 * 3) + 1;
ProcessMetrics::TotalsSummary summary = {};
const size_t kPrivate_CleanIndex = (4 * 3) + 1;
const size_t kPrivate_DirtyIndex = (5 * 3) + 1;
const size_t kSwapIndex = (9 * 3) + 1;
......@@ -402,85 +394,36 @@ bool ProcessMetrics::GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage)
ThreadRestrictions::ScopedAllowIO allow_io;
bool ret = ReadFileToString(totmaps_file, &totmaps_data);
if (!ret || totmaps_data.length() == 0)
return false;
return summary;
}
std::vector<std::string> totmaps_fields = SplitString(
totmaps_data, kWhitespaceASCII, KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
DCHECK_EQ("Pss:", totmaps_fields[kPssIndex-1]);
DCHECK_EQ("Private_Clean:", totmaps_fields[kPrivate_CleanIndex - 1]);
DCHECK_EQ("Private_Dirty:", totmaps_fields[kPrivate_DirtyIndex - 1]);
DCHECK_EQ("Swap:", totmaps_fields[kSwapIndex-1]);
int pss = 0;
int private_clean = 0;
int private_dirty = 0;
int swap = 0;
bool ret = true;
ret &= StringToInt(totmaps_fields[kPssIndex], &pss);
ret &= StringToInt(totmaps_fields[kPrivate_CleanIndex], &private_clean);
ret &= StringToInt(totmaps_fields[kPrivate_DirtyIndex], &private_dirty);
ret &= StringToInt(totmaps_fields[kSwapIndex], &swap);
// On ChromeOS, swap goes to zram. Count this as private / shared, as
// increased swap decreases available RAM to user processes, which would
// otherwise create surprising results.
ws_usage->priv = private_clean + private_dirty + swap;
ws_usage->shared = pss + swap;
ws_usage->shareable = 0;
ws_usage->swapped = swap;
return ret;
}
#endif
int private_clean_kb = 0;
int private_dirty_kb = 0;
int swap_kb = 0;
bool success = true;
success &=
StringToInt(totmaps_fields[kPrivate_CleanIndex], &private_clean_kb);
success &=
StringToInt(totmaps_fields[kPrivate_DirtyIndex], &private_dirty_kb);
success &= StringToInt(totmaps_fields[kSwapIndex], &swap_kb);
// Private and Shared working set sizes are obtained from /proc/<pid>/statm.
bool ProcessMetrics::GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage)
const {
// Use statm instead of smaps because smaps is:
// a) Large and slow to parse.
// b) Unavailable in the SUID sandbox.
// First get the page size, since everything is measured in pages.
// For details, see: man 5 proc.
const int page_size_kb = getpagesize() / 1024;
if (page_size_kb <= 0)
return false;
if (!success)
return summary;
std::string statm;
{
FilePath statm_file = internal::GetProcPidDir(process_).Append("statm");
// Synchronously reading files in /proc does not hit the disk.
ThreadRestrictions::ScopedAllowIO allow_io;
bool ret = ReadFileToString(statm_file, &statm);
if (!ret || statm.length() == 0)
return false;
}
std::vector<StringPiece> statm_vec =
SplitStringPiece(statm, " ", TRIM_WHITESPACE, SPLIT_WANT_ALL);
if (statm_vec.size() != 7)
return false; // Not the expected format.
int statm_rss;
int statm_shared;
bool ret = true;
ret &= StringToInt(statm_vec[1], &statm_rss);
ret &= StringToInt(statm_vec[2], &statm_shared);
ws_usage->priv = (statm_rss - statm_shared) * page_size_kb;
ws_usage->shared = statm_shared * page_size_kb;
summary.private_clean_kb = private_clean_kb;
summary.private_dirty_kb = private_dirty_kb;
summary.swap_kb = swap_kb;
// Sharable is not calculated, as it does not provide interesting data.
ws_usage->shareable = 0;
#if defined(OS_CHROMEOS)
// Can't get swapped memory from statm.
ws_usage->swapped = 0;
#endif
return ret;
return summary;
}
#endif
size_t GetSystemCommitCharge() {
SystemMemoryInfoKB meminfo;
......
......@@ -105,36 +105,6 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
return WrapUnique(new ProcessMetrics(process, port_provider));
}
void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const {
WorkingSetKBytes unused;
if (!GetCommittedAndWorkingSetKBytes(usage, &unused)) {
*usage = CommittedKBytes();
}
}
bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
CommittedKBytes unused;
return GetCommittedAndWorkingSetKBytes(&unused, ws_usage);
}
bool ProcessMetrics::GetCommittedAndWorkingSetKBytes(
CommittedKBytes* usage,
WorkingSetKBytes* ws_usage) const {
task_basic_info_64 task_info_data;
if (!GetTaskInfo(TaskForPid(process_), &task_info_data))
return false;
usage->priv = task_info_data.virtual_size / 1024;
usage->mapped = 0;
usage->image = 0;
ws_usage->priv = task_info_data.resident_size / 1024;
ws_usage->shareable = 0;
ws_usage->shared = 0;
return true;
}
ProcessMetrics::TaskVMInfo ProcessMetrics::GetTaskVMInfo() const {
TaskVMInfo info;
ChromeTaskVMInfo task_vm_info;
......
......@@ -21,37 +21,6 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
return WrapUnique(new ProcessMetrics(process));
}
namespace {
size_t GetWorkingSetSize() {
struct kinfo_proc info;
size_t length;
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_,
sizeof(struct kinfo_proc), 0 };
if (sysctl(mib, arraysize(mib), NULL, &length, NULL, 0) < 0)
return -1;
mib[5] = (length / sizeof(struct kinfo_proc));
if (sysctl(mib, arraysize(mib), &info, &length, NULL, 0) < 0)
return -1;
return info.p_vm_rssize * getpagesize();
}
} // namespace
bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
// TODO(bapt): be sure we can't be precise
size_t priv = GetWorkingSetSize();
if (!priv)
return false;
ws_usage->priv = priv / 1024;
ws_usage->shareable = 0;
ws_usage->shared = 0;
return true;
}
bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
return false;
}
......
......@@ -46,42 +46,6 @@ std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateProcessMetrics(
return WrapUnique(new ProcessMetrics(process));
}
void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const {
MEMORY_BASIC_INFORMATION mbi = {0};
size_t committed_private = 0;
size_t committed_mapped = 0;
size_t committed_image = 0;
void* base_address = NULL;
while (VirtualQueryEx(process_.Get(), base_address, &mbi, sizeof(mbi)) ==
sizeof(mbi)) {
if (mbi.State == MEM_COMMIT) {
if (mbi.Type == MEM_PRIVATE) {
committed_private += mbi.RegionSize;
} else if (mbi.Type == MEM_MAPPED) {
committed_mapped += mbi.RegionSize;
} else if (mbi.Type == MEM_IMAGE) {
committed_image += mbi.RegionSize;
} else {
NOTREACHED();
}
}
void* new_base = (static_cast<BYTE*>(mbi.BaseAddress)) + mbi.RegionSize;
// Avoid infinite loop by weird MEMORY_BASIC_INFORMATION.
// If we query 64bit processes in a 32bit process, VirtualQueryEx()
// returns such data.
if (new_base <= base_address) {
usage->image = 0;
usage->mapped = 0;
usage->priv = 0;
return;
}
base_address = new_base;
}
usage->image = committed_image / 1024;
usage->mapped = committed_mapped / 1024;
usage->priv = committed_private / 1024;
}
namespace {
class WorkingSetInformationBuffer {
......@@ -164,36 +128,6 @@ class WorkingSetInformationBuffer {
} // namespace
bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
size_t ws_private = 0;
size_t ws_shareable = 0;
size_t ws_shared = 0;
DCHECK(ws_usage);
memset(ws_usage, 0, sizeof(*ws_usage));
WorkingSetInformationBuffer buffer;
if (!buffer.QueryPageEntries(process_.Get()))
return false;
size_t num_page_entries = buffer.GetPageEntryCount();
for (size_t i = 0; i < num_page_entries; i++) {
if (buffer->WorkingSetInfo[i].Shared) {
ws_shareable++;
if (buffer->WorkingSetInfo[i].ShareCount > 1)
ws_shared++;
} else {
ws_private++;
}
}
ws_usage->priv = ws_private * PAGESIZE_KB;
ws_usage->shareable = ws_shareable * PAGESIZE_KB;
ws_usage->shared = ws_shared * PAGESIZE_KB;
return true;
}
static uint64_t FileTimeToUTC(const FILETIME& ftime) {
LARGE_INTEGER li;
li.LowPart = ftime.dwLowDateTime;
......
......@@ -335,9 +335,9 @@ int TabManagerDelegate::MemoryStat::EstimatedMemoryFreedKB(
base::ProcessHandle pid) {
std::unique_ptr<base::ProcessMetrics> process_metrics(
base::ProcessMetrics::CreateProcessMetrics(pid));
base::WorkingSetKBytes mem_usage;
process_metrics->GetWorkingSetKBytes(&mem_usage);
return mem_usage.priv;
base::ProcessMetrics::TotalsSummary summary =
process_metrics->GetTotalsSummary();
return summary.private_clean_kb + summary.private_dirty_kb + summary.swap_kb;
}
TabManagerDelegate::TabManagerDelegate(
......
......@@ -130,10 +130,9 @@ int64_t TaskGroupSampler::RefreshSwappedMem() {
DCHECK(worker_pool_sequenced_checker_.CalledOnValidSequence());
#if defined(OS_CHROMEOS)
base::WorkingSetKBytes ws_usage;
if (process_metrics_->GetWorkingSetKBytes(&ws_usage)) {
return ws_usage.swapped * 1024;
}
base::ProcessMetrics::TotalsSummary summary =
process_metrics_->GetTotalsSummary();
return summary.swap_kb * 1024;
#endif // defined(OS_CHROMEOS)
return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment