Add out of memory stats for graphics memory, discards per minute

BUG=175805
TEST=Added to browser_tests OomPriorityManagerTest. Also, manual test (see bug)

Review URL: https://codereview.chromium.org/12221159

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@182134 0039d316-1c4b-4281-b951-d872f2087c98
parent 003e76c9
......@@ -72,6 +72,11 @@ const char kExperiment[] = "LowMemoryMargin";
// value.
const int kAdjustmentIntervalSeconds = 10;
// For each period of this length we record a statistic to indicate whether
// or not the user experienced a low memory event. If you change this interval
// you must replace Tabs.Discard.DiscardInLastMinute with a new statistic.
const int kRecentTabDiscardIntervalSeconds = 60;
// If there has been no priority adjustment in this interval, we assume the
// machine was suspended and correct our timing statistics.
const int kSuspendThresholdSeconds = kAdjustmentIntervalSeconds * 4;
......@@ -88,6 +93,23 @@ int64 IdFromWebContents(WebContents* web_contents) {
return reinterpret_cast<int64>(web_contents);
}
// Records a statistics |sample| for UMA histogram |name| using a linear
// distribution of buckets.
void RecordLinearHistogram(const std::string& name,
int sample,
int maximum,
size_t bucket_count) {
// Do not use the UMA_HISTOGRAM_... macros here. They cache the Histogram
// instance and thus only work if |name| is constant.
base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
name,
1, // Minimum. The 0 bin for underflow is automatically added.
maximum + 1, // Ensure bucket size of |maximum| / |bucket_count|.
bucket_count + 2, // Account for the underflow and overflow bins.
base::Histogram::kUmaTargetedHistogramFlag);
counter->Add(sample);
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
......@@ -154,7 +176,8 @@ OomPriorityManager::TabStats::~TabStats() {
OomPriorityManager::OomPriorityManager()
: focused_tab_pid_(0),
discard_count_(0) {
discard_count_(0),
recent_tab_discard_(false) {
// We only need the low memory observer if we want to discard tabs.
if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoDiscardTabs))
low_memory_observer_.reset(new LowMemoryObserver);
......@@ -181,6 +204,13 @@ void OomPriorityManager::Start() {
this,
&OomPriorityManager::AdjustOomPriorities);
}
if (!recent_tab_discard_timer_.IsRunning()) {
recent_tab_discard_timer_.Start(
FROM_HERE,
TimeDelta::FromSeconds(kRecentTabDiscardIntervalSeconds),
this,
&OomPriorityManager::RecordRecentTabDiscard);
}
if (low_memory_observer_.get())
low_memory_observer_->Start();
start_time_ = TimeTicks::Now();
......@@ -188,6 +218,7 @@ void OomPriorityManager::Start() {
void OomPriorityManager::Stop() {
timer_.Stop();
recent_tab_discard_timer_.Stop();
if (low_memory_observer_.get())
low_memory_observer_->Stop();
}
......@@ -282,6 +313,7 @@ bool OomPriorityManager::DiscardTabById(int64 target_web_contents_id) {
// memory state that lead to the discard.
RecordDiscardStatistics();
model->DiscardWebContentsAt(idx);
recent_tab_discard_ = true;
return true;
}
}
......@@ -327,12 +359,22 @@ void OomPriorityManager::RecordDiscardStatistics() {
EXPERIMENT_HISTOGRAM_MEGABYTES("Tabs.Discard.MemAnonymousMB",
mem_anonymous_mb);
// Record graphics GEM object size in a histogram with 50 MB buckets.
int mem_graphics_gem_mb = 0;
if (memory.gem_size != -1)
mem_graphics_gem_mb = memory.gem_size / 1024 / 1024;
RecordLinearHistogram(
"Tabs.Discard.MemGraphicsMB", mem_graphics_gem_mb, 2500, 50);
// Record shared memory (used by renderer/GPU buffers).
int mem_shmem_mb = memory.shmem / 1024;
RecordLinearHistogram("Tabs.Discard.MemShmemMB", mem_shmem_mb, 2500, 50);
// On Intel, graphics objects are in anonymous pages, but on ARM they are
// not. For a total "allocated count" add in graphics pages on ARM.
int mem_allocated_mb = mem_anonymous_mb;
#if defined(ARCH_CPU_ARM_FAMILY)
if (memory.gem_size != -1)
mem_allocated_mb += memory.gem_size / 1024 / 1024;
mem_allocated_mb += mem_graphics_gem_mb;
#endif
EXPERIMENT_CUSTOM_COUNTS("Tabs.Discard.MemAllocatedMB", mem_allocated_mb,
256, 32768, 50)
......@@ -346,6 +388,15 @@ void OomPriorityManager::RecordDiscardStatistics() {
last_discard_time_ = TimeTicks::Now();
}
void OomPriorityManager::RecordRecentTabDiscard() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// If we change the interval we need to change the histogram name.
UMA_HISTOGRAM_BOOLEAN("Tabs.Discard.DiscardInLastMinute",
recent_tab_discard_);
// Reset for the next interval.
recent_tab_discard_ = false;
}
void OomPriorityManager::PurgeBrowserMemory() {
// Based on experimental evidence, attempts to free memory from renderers
// have been too slow to use in OOM situations (V8 garbage collection) or
......
......@@ -42,6 +42,9 @@ class OomPriorityManager : public content::NotificationObserver {
// Number of discard events since Chrome started.
int discard_count() const { return discard_count_; }
// See member comment.
bool recent_tab_discard() const { return recent_tab_discard_; }
void Start();
void Stop();
......@@ -91,6 +94,10 @@ class OomPriorityManager : public content::NotificationObserver {
// to manually test the system.
void RecordDiscardStatistics();
// Record whether we ran out of memory during a recent time interval.
// This allows us to normalize low memory statistics versus usage.
void RecordRecentTabDiscard();
// Purges data structures in the browser that can be easily recomputed.
void PurgeBrowserMemory();
......@@ -119,6 +126,7 @@ class OomPriorityManager : public content::NotificationObserver {
base::RepeatingTimer<OomPriorityManager> timer_;
base::OneShotTimer<OomPriorityManager> focus_tab_score_adjust_timer_;
base::RepeatingTimer<OomPriorityManager> recent_tab_discard_timer_;
content::NotificationRegistrar registrar_;
// This lock is for pid_to_oom_score_ and focus_tab_pid_.
......@@ -146,6 +154,10 @@ class OomPriorityManager : public content::NotificationObserver {
// Number of times we have discarded a tab, for statistics.
int discard_count_;
// Whether a tab discard event has occurred during the last time interval,
// used for statistics normalized by usage.
bool recent_tab_discard_;
DISALLOW_COPY_AND_ASSIGN(OomPriorityManager);
};
......
......@@ -24,6 +24,10 @@ typedef InProcessBrowserTest OomPriorityManagerTest;
IN_PROC_BROWSER_TEST_F(OomPriorityManagerTest, OomPriorityManagerBasics) {
using content::WindowedNotificationObserver;
chromeos::OomPriorityManager* oom_priority_manager =
g_browser_process->oom_priority_manager();
EXPECT_FALSE(oom_priority_manager->recent_tab_discard());
// Get three tabs open.
WindowedNotificationObserver load1(
content::NOTIFICATION_NAV_ENTRY_COMMITTED,
......@@ -83,6 +87,7 @@ IN_PROC_BROWSER_TEST_F(OomPriorityManagerTest, OomPriorityManagerBasics) {
EXPECT_TRUE(browser()->tab_strip_model()->IsTabDiscarded(0));
EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(1));
EXPECT_FALSE(browser()->tab_strip_model()->IsTabDiscarded(2));
EXPECT_TRUE(oom_priority_manager->recent_tab_discard());
// Run discard again, make sure it kills the second tab.
EXPECT_TRUE(g_browser_process->oom_priority_manager()->DiscardTab());
......
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