Commit 4159f36e authored by bashi's avatar bashi Committed by Commit bot

Record swap metrics

This CL adds SwapMetricsObserver which records swap rates and reports
them as platform-specific metrics. The purpose of adding these metrics
is to measure the impact of actions we take to free up memory. If we
aggressively free up memory under high memory pressure, we may touch
pages which are already swapped out (or compressed). In such cases
thrashing could happen and we are making the situation worse.
Swap rates and page compression/decompression rate would be good
indicators of thrashing. Metrics will be recorded every 60 seconds.

This CL only adds metrics for Android/ChromeOS/Linux. Follow-up CLs
will add them for macOS.

BUG=617492

Review-Url: https://codereview.chromium.org/2824133002
Cr-Commit-Position: refs/heads/master@{#468266}
parent 96988fae
...@@ -990,6 +990,12 @@ source_set("browser") { ...@@ -990,6 +990,12 @@ source_set("browser") {
"memory/memory_monitor_win.h", "memory/memory_monitor_win.h",
"memory/memory_pressure_controller_impl.cc", "memory/memory_pressure_controller_impl.cc",
"memory/memory_pressure_controller_impl.h", "memory/memory_pressure_controller_impl.h",
"memory/swap_metrics_observer.cc",
"memory/swap_metrics_observer.h",
"memory/swap_metrics_observer_linux.cc",
"memory/swap_metrics_observer_linux.h",
"memory/swap_metrics_observer_mac.cc",
"memory/swap_metrics_observer_win.cc",
"message_port_provider.cc", "message_port_provider.cc",
"mime_registry_impl.cc", "mime_registry_impl.cc",
"mime_registry_impl.h", "mime_registry_impl.h",
...@@ -1864,6 +1870,14 @@ source_set("browser") { ...@@ -1864,6 +1870,14 @@ source_set("browser") {
"web_contents/web_contents_view_android.cc", "web_contents/web_contents_view_android.cc",
"web_contents/web_contents_view_android.h", "web_contents/web_contents_view_android.h",
] ]
set_sources_assignment_filter([])
sources += [
"memory/swap_metrics_observer_linux.cc",
"memory/swap_metrics_observer_linux.h",
]
set_sources_assignment_filter(sources_assignment_filter)
sources -= [ sources -= [
"browser_ipc_logging.cc", "browser_ipc_logging.cc",
"media/session/audio_focus_delegate_default.cc", "media/session/audio_focus_delegate_default.cc",
......
...@@ -68,6 +68,7 @@ ...@@ -68,6 +68,7 @@
#include "content/browser/loader_delegate_impl.h" #include "content/browser/loader_delegate_impl.h"
#include "content/browser/media/media_internals.h" #include "content/browser/media/media_internals.h"
#include "content/browser/memory/memory_coordinator_impl.h" #include "content/browser/memory/memory_coordinator_impl.h"
#include "content/browser/memory/swap_metrics_observer.h"
#include "content/browser/net/browser_online_state_observer.h" #include "content/browser/net/browser_online_state_observer.h"
#include "content/browser/renderer_host/media/media_stream_manager.h" #include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_process_host_impl.h"
...@@ -1599,6 +1600,10 @@ void BrowserMainLoop::InitializeMemoryManagementComponent() { ...@@ -1599,6 +1600,10 @@ void BrowserMainLoop::InitializeMemoryManagementComponent() {
base::Unretained(coordinator))); base::Unretained(coordinator)));
} }
} }
auto* swap_metrics_observer = SwapMetricsObserver::GetInstance();
if (swap_metrics_observer)
swap_metrics_observer->Start();
} }
bool BrowserMainLoop::InitializeToolkit() { bool BrowserMainLoop::InitializeToolkit() {
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/memory/swap_metrics_observer.h"
#include "base/bind.h"
#include "base/threading/thread_task_runner_handle.h"
namespace content {
namespace {
// Time between updating swap rates.
const int kSwapMetricsIntervalSeconds = 60;
} // namespace
SwapMetricsObserver::SwapMetricsObserver()
: update_interval_(
base::TimeDelta::FromSeconds(kSwapMetricsIntervalSeconds)) {}
SwapMetricsObserver::~SwapMetricsObserver() {}
void SwapMetricsObserver::Start() {
timer_.Start(FROM_HERE, update_interval_, this,
&SwapMetricsObserver::UpdateMetrics);
}
void SwapMetricsObserver::Stop() {
last_ticks_ = base::TimeTicks();
timer_.Stop();
}
void SwapMetricsObserver::UpdateMetrics() {
base::TimeTicks now = base::TimeTicks::Now();
base::TimeDelta interval =
last_ticks_.is_null() ? base::TimeDelta() : now - last_ticks_;
UpdateMetricsInternal(interval);
last_ticks_ = now;
}
} // namespace content
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_H_
#define CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_H_
#include "base/time/time.h"
#include "base/timer/timer.h"
namespace content {
// This class observes system's swapping behavior to collect metrics.
// Metrics can be platform-specific.
class SwapMetricsObserver {
public:
// This returns nullptr when swap metrics are not available on the system.
static SwapMetricsObserver* GetInstance();
// Starts observing swap metrics.
void Start();
// Stop observing swap metrics.
void Stop();
protected:
SwapMetricsObserver();
virtual ~SwapMetricsObserver();
// Periodically called to update swap metrics.
void UpdateMetrics();
// Platform-dependent parts of UpdateMetrics(). |interval| is the elapsed time
// since the last UpdateMetrics() call. |interval| will be zero when this
// function is called for the first time.
virtual void UpdateMetricsInternal(base::TimeDelta interval) = 0;
private:
// The interval between metrics updates.
base::TimeDelta update_interval_;
// A periodic timer to update swap metrics.
base::RepeatingTimer timer_;
// Holds the last TimeTicks when swap metrics are updated.
base::TimeTicks last_ticks_;
DISALLOW_COPY_AND_ASSIGN(SwapMetricsObserver);
};
} // namespace
#endif // CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_H_
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/memory/swap_metrics_observer_linux.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/process_metrics.h"
namespace content {
namespace {
bool HasSwap() {
base::SystemMemoryInfoKB memory_info;
if (!base::GetSystemMemoryInfo(&memory_info))
return false;
return memory_info.swap_total > 0;
}
} // namespace
// static
SwapMetricsObserver* SwapMetricsObserver::GetInstance() {
static SwapMetricsObserverLinux* instance =
HasSwap() ? new SwapMetricsObserverLinux() : nullptr;
return instance;
}
SwapMetricsObserverLinux::SwapMetricsObserverLinux() {}
SwapMetricsObserverLinux::~SwapMetricsObserverLinux() {}
void SwapMetricsObserverLinux::UpdateMetricsInternal(base::TimeDelta interval) {
base::SystemMemoryInfoKB memory_info;
if (!base::GetSystemMemoryInfo(&memory_info)) {
Stop();
return;
}
double in_counts = memory_info.pswpin - last_pswpin_;
double out_counts = memory_info.pswpout - last_pswpout_;
last_pswpin_ = memory_info.pswpin;
last_pswpout_ = memory_info.pswpout;
if (interval.is_zero())
return;
UMA_HISTOGRAM_COUNTS_10000("Memory.Experimental.SwapInPerSecond",
in_counts / interval.InSecondsF());
UMA_HISTOGRAM_COUNTS_10000("Memory.Experimental.SwapOutPerSecond",
out_counts / interval.InSecondsF());
}
} // namespace content
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_LINUX_H_
#define CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_LINUX_H_
#include "content/browser/memory/swap_metrics_observer.h"
namespace content {
class SwapMetricsObserverLinux : public SwapMetricsObserver {
public:
SwapMetricsObserverLinux();
~SwapMetricsObserverLinux() override;
protected:
void UpdateMetricsInternal(base::TimeDelta interval) override;
private:
uint64_t last_pswpin_ = 0;
uint64_t last_pswpout_ = 0;
};
} // namespace content
#endif // CONTENT_BROWSER_MEMORY_SWAP_METRICS_OBSERVER_LINUX_H_
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/memory/swap_metrics_observer.h"
namespace content {
// static
SwapMetricsObserver* SwapMetricsObserver::GetInstance() {
// TODO(bashi): Implement SwapMetricsObserver for macOS.
return nullptr;
}
} // namespace content
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/memory/swap_metrics_observer.h"
namespace content {
// static
SwapMetricsObserver* SwapMetricsObserver::GetInstance() {
// SwapMetricsObserver isn't available on Windows for now.
// TODO(bashi): Figure out a way to measure swap rates on Windows.
return nullptr;
}
} // namespace content
...@@ -29448,6 +29448,20 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. ...@@ -29448,6 +29448,20 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
</summary> </summary>
</histogram> </histogram>
<histogram name="Memory.Experimental.SwapInPerSecond" units="swaps/s">
<owner>bashi@chromium.org</owner>
<summary>
The number of swap-ins per second. Recorded every 60 seconds.
</summary>
</histogram>
<histogram name="Memory.Experimental.SwapOutPerSecond" units="swaps/s">
<owner>bashi@chromium.org</owner>
<summary>
The number of swap-outs per second. Recorded every 60 seconds.
</summary>
</histogram>
<histogram name="Memory.Extension" units="KB"> <histogram name="Memory.Extension" units="KB">
<owner>hajimehoshi@chromium.org</owner> <owner>hajimehoshi@chromium.org</owner>
<owner>kenjibaheux@google.com</owner> <owner>kenjibaheux@google.com</owner>
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