Index: components/arc/metrics/oom_kills_monitor.cc |
diff --git a/components/arc/metrics/oom_kills_monitor.cc b/components/arc/metrics/oom_kills_monitor.cc |
deleted file mode 100644 |
index 719b778eaf9dbc3e54d9939ce11a0eb2e6fe233d..0000000000000000000000000000000000000000 |
--- a/components/arc/metrics/oom_kills_monitor.cc |
+++ /dev/null |
@@ -1,206 +0,0 @@ |
-// Copyright 2016 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 "components/arc/metrics/oom_kills_monitor.h" |
- |
-#include <errno.h> |
-#include <fcntl.h> |
-#include <stdio.h> |
- |
-#include <vector> |
- |
-#include "base/bind.h" |
-#include "base/debug/leak_annotations.h" |
-#include "base/files/file_util.h" |
-#include "base/files/scoped_file.h" |
-#include "base/location.h" |
-#include "base/logging.h" |
-#include "base/memory/ptr_util.h" |
-#include "base/metrics/histogram_macros.h" |
-#include "base/posix/safe_strerror.h" |
-#include "base/sequenced_task_runner.h" |
-#include "base/strings/string_number_conversions.h" |
-#include "base/strings/string_piece.h" |
-#include "base/strings/string_split.h" |
-#include "base/time/time.h" |
-#include "components/arc/metrics/oom_kills_histogram.h" |
-#include "third_party/re2/src/re2/re2.h" |
-#include "third_party/re2/src/re2/stringpiece.h" |
- |
-namespace arc { |
- |
-using base::StringPiece; |
- |
-using base::SequencedWorkerPool; |
-using base::TimeDelta; |
- |
-namespace { |
- |
-int64_t GetTimestamp(const StringPiece& line) { |
- std::vector<StringPiece> fields = base::SplitStringPiece( |
- line, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
- |
- int64_t timestamp = -1; |
- // Timestamp is the third field in a line of /dev/kmsg. |
- if (fields.size() < 3 || !base::StringToInt64(fields[2], ×tamp)) |
- return -1; |
- return timestamp; |
-} |
- |
-bool GetTimeDelta( |
- const StringPiece& line, int64_t* last, TimeDelta* time_delta) { |
- int64_t now = GetTimestamp(line); |
- if (now < 0) |
- return false; |
- |
- // Sets to |kMaxOomMemoryKillTimeSecs| for the first kill event. |
- if (*last < 0) |
- *time_delta = TimeDelta::FromSeconds(kMaxOomMemoryKillTimeDeltaSecs); |
- else |
- *time_delta = TimeDelta::FromMicroseconds(now - *last); |
- |
- *last = now; |
- |
- return true; |
-} |
- |
-void LogOOMKill(const StringPiece& line) { |
- static int64_t last_timestamp = -1; |
- static int oom_kills = 0; |
- |
- // Sample log line: |
- // 3,1362,97646497541,-;Out of memory: Kill process 29582 (android.vending) |
- // score 961 or sacrifice child. |
- int oom_badness; |
- TimeDelta time_delta; |
- if (RE2::PartialMatch(re2::StringPiece(line.data(), line.size()), |
- "Out of memory: Kill process .* score (\\d+)", |
- &oom_badness)) { |
- ++oom_kills; |
- // Report the cumulative count of killed process in one login session. |
- // For example if there are 3 processes killed, it would report 1 for the |
- // first kill, 2 for the second kill, then 3 for the final kill. |
- // It doesn't report a final count at the end of a user session because |
- // the code runs in a dedicated thread and never ends until browser shutdown |
- // (or logout on Chrome OS). And on browser shutdown the thread may be |
- // terminated brutally so there's no chance to execute a "final" block. |
- // More specifically, code outside the main loop of OomKillsMonitor::Run() |
- // are not guaranteed to be executed. |
- UMA_HISTOGRAM_CUSTOM_COUNTS( |
- "Arc.OOMKills.Count", oom_kills, 1, 1000, 1001); |
- |
- // In practice most process has oom_badness < 1000, but |
- // strictly speaking the number could be [1, 2000]. What it really |
- // means is the baseline, proportion of memory used (normalized to |
- // [0, 1000]), plus an adjustment score oom_score_adj [-1000, 1000], |
- // truncated to 1 if negative (0 means never kill). |
- // Ref: https://lwn.net/Articles/396552/ |
- UMA_HISTOGRAM_CUSTOM_COUNTS( |
- "Arc.OOMKills.Score", oom_badness, 1, 2000, 2001); |
- |
- if (GetTimeDelta(line, &last_timestamp, &time_delta)) { |
- UMA_HISTOGRAM_OOM_KILL_TIME_INTERVAL( |
- "Arc.OOMKills.TimeDelta", time_delta); |
- } |
- } |
-} |
- |
-void LogLowMemoryKill(const StringPiece& line) { |
- static int64_t last_timestamp = -1; |
- static int low_memory_kills = 0; |
- |
- int freed_size; |
- TimeDelta time_delta; |
- // Sample log line: |
- // 6,2302,533604004,-;lowmemorykiller: Killing 'externalstorage' (21742), |
- // adj 1000,\x0a to free 27320kB on behalf of 'kswapd0' (47) because\x0a |
- // cache 181920kB is below limit 184320kB for oom_score_adj 1000\x0a |
- // Free memory is 1228kB above reserved |
- if (RE2::PartialMatch(re2::StringPiece(line.data(), line.size()), |
- "lowmemorykiller: .* to free (\\d+)kB", |
- &freed_size)) { |
- // Report the count for each lowmemorykill event. See comments in |
- // LogOOMKill(). |
- ++low_memory_kills; |
- UMA_HISTOGRAM_CUSTOM_COUNTS( |
- "Arc.LowMemoryKiller.Count", low_memory_kills, 1, 1000, 1001); |
- |
- UMA_HISTOGRAM_MEMORY_KB("Arc.LowMemoryKiller.FreedSize", freed_size); |
- |
- if (GetTimeDelta(line, &last_timestamp, &time_delta)) { |
- UMA_HISTOGRAM_OOM_KILL_TIME_INTERVAL( |
- "Arc.LowMemoryKiller.TimeDelta", time_delta); |
- } |
- } |
-} |
- |
-} // namespace |
- |
-OomKillsMonitor::Handle::Handle(OomKillsMonitor* outer) : outer_(outer) { |
- DCHECK(outer_); |
-} |
- |
-OomKillsMonitor::Handle::~Handle() { |
- outer_->is_shutting_down_.Set(); |
-} |
- |
-OomKillsMonitor::OomKillsMonitor() { |
- base::SimpleThread::Options non_joinable_options; |
- non_joinable_options.joinable = false; |
- non_joinable_worker_thread_ = base::MakeUnique<base::DelegateSimpleThread>( |
- this, "oom_kills_monitor", non_joinable_options); |
- non_joinable_worker_thread_->Start(); |
-} |
- |
-OomKillsMonitor::~OomKillsMonitor() { |
- // The instance has to be leaked on shutdown as it is referred to by a |
- // non-joinable thread but ~OomKillsMonitor() can't be explicitly deleted as |
- // it overrides ~SimpleThread(), it should nevertheless never be invoked. |
- NOTREACHED(); |
-} |
- |
-// static |
-OomKillsMonitor::Handle OomKillsMonitor::StartMonitoring() { |
-#if DCHECK_IS_ON() |
- static volatile bool monitoring_active = false; |
- DCHECK(!monitoring_active); |
- monitoring_active = true; |
-#endif |
- |
- // Instantiate the OomKillsMonitor and its underlying thread. The |
- // OomKillsMonitor itself has to be leaked on shutdown per having a |
- // non-joinable thread associated to its state. The OomKillsMonitor::Handle |
- // will notify the OomKillsMonitor when it is destroyed so that the underlying |
- // thread can at a minimum not do extra work during shutdown. |
- OomKillsMonitor* instance = new OomKillsMonitor; |
- ANNOTATE_LEAKING_OBJECT_PTR(instance); |
- return Handle(instance); |
-} |
- |
-void OomKillsMonitor::Run() { |
- base::ScopedFILE kmsg_handle( |
- base::OpenFile(base::FilePath("/dev/kmsg"), "r")); |
- if (!kmsg_handle) { |
- LOG(WARNING) << "Open /dev/kmsg failed: " << base::safe_strerror(errno); |
- return; |
- } |
- // Skip kernel messages prior to the instantiation of this object to avoid |
- // double reporting. |
- fseek(kmsg_handle.get(), 0, SEEK_END); |
- |
- static const int kMaxBufSize = 512; |
- char buf[kMaxBufSize]; |
- |
- while (fgets(buf, kMaxBufSize, kmsg_handle.get())) { |
- if (is_shutting_down_.IsSet()) { |
- DVLOG(1) << "Chrome is shutting down, exit now."; |
- break; |
- } |
- const StringPiece buf_string(buf); |
- LogOOMKill(buf_string); |
- LogLowMemoryKill(buf_string); |
- } |
-} |
- |
-} // namespace arc |