Add memory stats for linux page cycler. On linux, we collect
the final RSS size and the total VM size. Review URL: http://codereview.chromium.org/113217 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15814 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@@ -323,12 +323,16 @@ class ProcessMetrics {
|
|||||||
~ProcessMetrics();
|
~ProcessMetrics();
|
||||||
|
|
||||||
// Returns the current space allocated for the pagefile, in bytes (these pages
|
// Returns the current space allocated for the pagefile, in bytes (these pages
|
||||||
// may or may not be in memory).
|
// may or may not be in memory). On Linux, this returns the total virtual
|
||||||
|
// memory size.
|
||||||
size_t GetPagefileUsage() const;
|
size_t GetPagefileUsage() const;
|
||||||
// Returns the peak space allocated for the pagefile, in bytes.
|
// Returns the peak space allocated for the pagefile, in bytes.
|
||||||
size_t GetPeakPagefileUsage() const;
|
size_t GetPeakPagefileUsage() const;
|
||||||
// Returns the current working set size, in bytes.
|
// Returns the current working set size, in bytes. On Linux, this returns
|
||||||
|
// the resident set size.
|
||||||
size_t GetWorkingSetSize() const;
|
size_t GetWorkingSetSize() const;
|
||||||
|
// Returns the peak working set size, in bytes.
|
||||||
|
size_t GetPeakWorkingSetSize() const;
|
||||||
// Returns private usage, in bytes. Private bytes is the amount
|
// Returns private usage, in bytes. Private bytes is the amount
|
||||||
// of memory currently allocated to a process that cannot be shared.
|
// of memory currently allocated to a process that cannot be shared.
|
||||||
// Note: returns 0 on unsupported OSes: prior to XP SP2.
|
// Note: returns 0 on unsupported OSes: prior to XP SP2.
|
||||||
|
@@ -25,6 +25,18 @@ enum ParsingState {
|
|||||||
KEY_VALUE
|
KEY_VALUE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Reads /proc/<pid>/stat and populates |proc_stats| with the values split by
|
||||||
|
// spaces.
|
||||||
|
void GetProcStats(pid_t pid, std::vector<std::string>* proc_stats) {
|
||||||
|
FilePath stat_file("/proc");
|
||||||
|
stat_file = stat_file.Append(IntToString(pid));
|
||||||
|
stat_file = stat_file.Append("stat");
|
||||||
|
std::string mem_stats;
|
||||||
|
if (!file_util::ReadFileToString(stat_file, &mem_stats))
|
||||||
|
return;
|
||||||
|
SplitString(mem_stats, ' ', proc_stats);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
@@ -187,11 +199,46 @@ bool NamedProcessIterator::IncludeEntry() {
|
|||||||
return filter_->Includes(entry_.pid, entry_.ppid);
|
return filter_->Includes(entry_.pid, entry_.ppid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On linux, we return vsize.
|
||||||
|
size_t ProcessMetrics::GetPagefileUsage() const {
|
||||||
|
std::vector<std::string> proc_stats;
|
||||||
|
GetProcStats(process_, &proc_stats);
|
||||||
|
const size_t kVmSize = 22;
|
||||||
|
if (proc_stats.size() > kVmSize)
|
||||||
|
return static_cast<size_t>(StringToInt(proc_stats[kVmSize]));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ProcessMetrics::GetPeakPagefileUsage() const {
|
||||||
|
NOTIMPLEMENTED();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// On linux, we return RSS.
|
||||||
|
size_t ProcessMetrics::GetWorkingSetSize() const {
|
||||||
|
std::vector<std::string> proc_stats;
|
||||||
|
GetProcStats(process_, &proc_stats);
|
||||||
|
const size_t kVmRss = 23;
|
||||||
|
if (proc_stats.size() > kVmRss) {
|
||||||
|
size_t num_pages = static_cast<size_t>(StringToInt(proc_stats[kVmRss]));
|
||||||
|
return num_pages * getpagesize();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ProcessMetrics::GetPeakWorkingSetSize() const {
|
||||||
|
NOTIMPLEMENTED();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// To have /proc/self/io file you must enable CONFIG_TASK_IO_ACCOUNTING
|
// To have /proc/self/io file you must enable CONFIG_TASK_IO_ACCOUNTING
|
||||||
// in your kernel configuration.
|
// in your kernel configuration.
|
||||||
bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
|
bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
|
||||||
std::string proc_io_contents;
|
std::string proc_io_contents;
|
||||||
if (!file_util::ReadFileToString(L"/proc/self/io", &proc_io_contents))
|
FilePath io_file("/proc");
|
||||||
|
io_file = io_file.Append(IntToString(process_));
|
||||||
|
io_file = io_file.Append("io");
|
||||||
|
if (!file_util::ReadFileToString(io_file, &proc_io_contents))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
(*io_counters).OtherOperationCount = 0;
|
(*io_counters).OtherOperationCount = 0;
|
||||||
|
@@ -233,4 +233,24 @@ bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ProcessMetrics::GetPagefileUsage() const {
|
||||||
|
NOTIMPLEMENTED();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ProcessMetrics::GetPeakPagefileUsage() const {
|
||||||
|
NOTIMPLEMENTED();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ProcessMetrics::GetWorkingSetSize() const {
|
||||||
|
NOTIMPLEMENTED();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ProcessMetrics::GetPeakWorkingSetSize() const {
|
||||||
|
NOTIMPLEMENTED();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace base
|
} // namespace base
|
||||||
|
@@ -520,6 +520,15 @@ size_t ProcessMetrics::GetWorkingSetSize() const {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the peak working set size, in bytes.
|
||||||
|
size_t ProcessMetrics::GetPeakWorkingSetSize() const {
|
||||||
|
PROCESS_MEMORY_COUNTERS pmc;
|
||||||
|
if (GetProcessMemoryInfo(process_, &pmc, sizeof(pmc))) {
|
||||||
|
return pmc.PeakWorkingSetSize;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t ProcessMetrics::GetPrivateBytes() const {
|
size_t ProcessMetrics::GetPrivateBytes() const {
|
||||||
// PROCESS_MEMORY_COUNTERS_EX is not supported until XP SP2.
|
// PROCESS_MEMORY_COUNTERS_EX is not supported until XP SP2.
|
||||||
// GetProcessMemoryInfo() will simply fail on prior OS. So the requested
|
// GetProcessMemoryInfo() will simply fail on prior OS. So the requested
|
||||||
|
@@ -2912,6 +2912,7 @@
|
|||||||
'target_name': 'page_cycler_tests',
|
'target_name': 'page_cycler_tests',
|
||||||
'type': 'executable',
|
'type': 'executable',
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
|
'app',
|
||||||
'chrome_resources',
|
'chrome_resources',
|
||||||
'chrome_strings',
|
'chrome_strings',
|
||||||
'test_support_ui',
|
'test_support_ui',
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
#include "chrome/test/automation/window_proxy.h"
|
#include "chrome/test/automation/window_proxy.h"
|
||||||
#include "chrome/test/chrome_process_util.h"
|
#include "chrome/test/chrome_process_util.h"
|
||||||
#include "chrome/test/ui/ui_test.h"
|
#include "chrome/test/ui/ui_test.h"
|
||||||
#include "chrome/test/perf/mem_usage.h"
|
|
||||||
#include "googleurl/src/gurl.h"
|
#include "googleurl/src/gurl.h"
|
||||||
#include "net/base/net_util.h"
|
#include "net/base/net_util.h"
|
||||||
|
|
||||||
@@ -84,8 +83,6 @@ class PageCyclerTest : public UITest {
|
|||||||
ASSERT_FALSE(timings->empty());
|
ASSERT_FALSE(timings->empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
// TODO(port): Port chrome_process_util and remove windowsisms.
|
|
||||||
void PrintIOPerfInfo(const char* test_name) {
|
void PrintIOPerfInfo(const char* test_name) {
|
||||||
FilePath data_dir;
|
FilePath data_dir;
|
||||||
PathService::Get(chrome::DIR_USER_DATA, &data_dir);
|
PathService::Get(chrome::DIR_USER_DATA, &data_dir);
|
||||||
@@ -100,10 +97,10 @@ class PageCyclerTest : public UITest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scoped_ptr<base::ProcessMetrics> process_metrics;
|
scoped_ptr<base::ProcessMetrics> process_metrics;
|
||||||
IO_COUNTERS io_counters;
|
|
||||||
process_metrics.reset(
|
process_metrics.reset(
|
||||||
base::ProcessMetrics::CreateProcessMetrics(process_handle));
|
base::ProcessMetrics::CreateProcessMetrics(process_handle));
|
||||||
ZeroMemory(&io_counters, sizeof(io_counters));
|
IoCounters io_counters;
|
||||||
|
memset(&io_counters, 0, sizeof(io_counters));
|
||||||
|
|
||||||
if (process_metrics.get()->GetIOCounters(&io_counters)) {
|
if (process_metrics.get()->GetIOCounters(&io_counters)) {
|
||||||
// Print out IO performance. We assume that the values can be
|
// Print out IO performance. We assume that the values can be
|
||||||
@@ -163,35 +160,50 @@ class PageCyclerTest : public UITest {
|
|||||||
|
|
||||||
ChromeProcessList::const_iterator it;
|
ChromeProcessList::const_iterator it;
|
||||||
for (it = chrome_processes.begin(); it != chrome_processes.end(); ++it) {
|
for (it = chrome_processes.begin(); it != chrome_processes.end(); ++it) {
|
||||||
size_t peak_virtual_size;
|
base::ProcessHandle process_handle;
|
||||||
size_t current_virtual_size;
|
if (!base::OpenProcessHandle(*it, &process_handle)) {
|
||||||
size_t peak_working_set_size;
|
NOTREACHED();
|
||||||
size_t current_working_set_size;
|
|
||||||
if (GetMemoryInfo(*it, &peak_virtual_size, ¤t_virtual_size,
|
|
||||||
&peak_working_set_size, ¤t_working_set_size)) {
|
|
||||||
std::string chrome_name = (*it == browser_process_pid) ? "_b" : "_r";
|
|
||||||
|
|
||||||
std::string trace_name(test_name);
|
|
||||||
PrintResult("vm_peak", chrome_name,
|
|
||||||
"vm_pk" + chrome_name + trace_name,
|
|
||||||
peak_virtual_size, "bytes",
|
|
||||||
true /* important */);
|
|
||||||
PrintResult("vm_final", chrome_name,
|
|
||||||
"vm_f" + chrome_name + trace_name,
|
|
||||||
current_virtual_size, "bytes",
|
|
||||||
false /* not important */);
|
|
||||||
PrintResult("ws_peak", chrome_name,
|
|
||||||
"ws_pk" + chrome_name + trace_name,
|
|
||||||
peak_working_set_size, "bytes",
|
|
||||||
true /* important */);
|
|
||||||
PrintResult("ws_final", chrome_name,
|
|
||||||
"ws_pk" + chrome_name + trace_name,
|
|
||||||
current_working_set_size, "bytes",
|
|
||||||
false /* not important */);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scoped_ptr<base::ProcessMetrics> process_metrics;
|
||||||
|
process_metrics.reset(
|
||||||
|
base::ProcessMetrics::CreateProcessMetrics(process_handle));
|
||||||
|
|
||||||
|
std::string chrome_name = (*it == browser_process_pid) ? "_b" : "_r";
|
||||||
|
|
||||||
|
std::string trace_name(test_name);
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
PrintResult("vm_peak", chrome_name,
|
||||||
|
"vm_pk" + chrome_name + trace_name,
|
||||||
|
process_metrics->GetPeakPagefileUsage(), "bytes",
|
||||||
|
true /* important */);
|
||||||
|
PrintResult("vm_final", chrome_name,
|
||||||
|
"vm_f" + chrome_name + trace_name,
|
||||||
|
process_metrics->GetPagefileUsage(), "bytes",
|
||||||
|
false /* not important */);
|
||||||
|
PrintResult("ws_peak", chrome_name,
|
||||||
|
"ws_pk" + chrome_name + trace_name,
|
||||||
|
process_metrics->GetPeakWorkingSetSize(), "bytes",
|
||||||
|
true /* important */);
|
||||||
|
PrintResult("ws_final", chrome_name,
|
||||||
|
"ws_f" + chrome_name + trace_name,
|
||||||
|
process_metrics->GetWorkingSetSize(), "bytes",
|
||||||
|
false /* not important */);
|
||||||
|
#elif defined(OS_LINUX)
|
||||||
|
PrintResult("vm_size_final", chrome_name,
|
||||||
|
"vm_size_f" + chrome_name + trace_name,
|
||||||
|
process_metrics->GetPagefileUsage(), "bytes",
|
||||||
|
true /* important */);
|
||||||
|
PrintResult("vm_rss_final", chrome_name,
|
||||||
|
"vm_rss_f" + chrome_name + trace_name,
|
||||||
|
process_metrics->GetWorkingSetSize(), "bytes",
|
||||||
|
true /* important */);
|
||||||
|
#else
|
||||||
|
NOTIMPLEMENTED();
|
||||||
|
#endif
|
||||||
|
base::CloseProcessHandle(process_handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // defined(OS_WIN)
|
|
||||||
|
|
||||||
// When use_http is true, the test name passed here will be used directly in
|
// When use_http is true, the test name passed here will be used directly in
|
||||||
// the path to the test data, so it must be safe for use in a URL without
|
// the path to the test data, so it must be safe for use in a URL without
|
||||||
@@ -204,11 +216,8 @@ class PageCyclerTest : public UITest {
|
|||||||
if (timings.empty())
|
if (timings.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
// TODO(port): Enable when Print{MemoryUsage,IOPerf}Info are ported.
|
|
||||||
PrintMemoryUsageInfo("");
|
PrintMemoryUsageInfo("");
|
||||||
PrintIOPerfInfo("");
|
PrintIOPerfInfo("");
|
||||||
#endif // defined(OS_WIN)
|
|
||||||
|
|
||||||
wprintf(L"\nPages: [%ls]\n", pages.c_str());
|
wprintf(L"\nPages: [%ls]\n", pages.c_str());
|
||||||
PrintResultList("times", "", "t", timings, "ms",
|
PrintResultList("times", "", "t", timings, "ms",
|
||||||
@@ -224,7 +233,13 @@ class PageCyclerReferenceTest : public PageCyclerTest {
|
|||||||
FilePath dir;
|
FilePath dir;
|
||||||
PathService::Get(chrome::DIR_TEST_TOOLS, &dir);
|
PathService::Get(chrome::DIR_TEST_TOOLS, &dir);
|
||||||
dir = dir.AppendASCII("reference_build");
|
dir = dir.AppendASCII("reference_build");
|
||||||
|
#if defined(OS_WIN)
|
||||||
dir = dir.AppendASCII("chrome");
|
dir = dir.AppendASCII("chrome");
|
||||||
|
#elif defined(OS_LINUX)
|
||||||
|
dir = dir.AppendASCII("chrome_linux");
|
||||||
|
#elif defined(OS_MACOSX)
|
||||||
|
dir = dir.AppendASCII("chrome_mac");
|
||||||
|
#endif
|
||||||
browser_directory_ = dir;
|
browser_directory_ = dir;
|
||||||
UITest::SetUp();
|
UITest::SetUp();
|
||||||
}
|
}
|
||||||
@@ -236,11 +251,8 @@ class PageCyclerReferenceTest : public PageCyclerTest {
|
|||||||
if (timings.empty())
|
if (timings.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
// TODO(port): Enable when Print{MemoryUsage,IOPerf}Info are ported.
|
|
||||||
PrintMemoryUsageInfo("_ref");
|
PrintMemoryUsageInfo("_ref");
|
||||||
PrintIOPerfInfo("_ref");
|
PrintIOPerfInfo("_ref");
|
||||||
#endif // defined(OS_WIN)
|
|
||||||
|
|
||||||
PrintResultList("times", "", "t_ref", timings, "ms",
|
PrintResultList("times", "", "t_ref", timings, "ms",
|
||||||
true /* important */);
|
true /* important */);
|
||||||
|
Reference in New Issue
Block a user