OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/chromeos/arc/arc_low_memory_killer_monitor.h" |
| 6 |
| 7 #include <errno.h> |
| 8 #include <fcntl.h> |
| 9 #include <stdio.h> |
| 10 |
| 11 #include <vector> |
| 12 |
| 13 #include "base/bind.h" |
| 14 #include "base/files/file_util.h" |
| 15 #include "base/location.h" |
| 16 #include "base/logging.h" |
| 17 #include "base/metrics/histogram_macros.h" |
| 18 #include "base/posix/safe_strerror.h" |
| 19 #include "base/sequenced_task_runner.h" |
| 20 #include "base/strings/string_number_conversions.h" |
| 21 #include "base/strings/string_split.h" |
| 22 #include "base/time/time.h" |
| 23 #include "third_party/re2/src/re2/re2.h" |
| 24 |
| 25 namespace arc { |
| 26 |
| 27 using base::SequencedWorkerPool; |
| 28 using base::StringPiece; |
| 29 using base::TimeDelta; |
| 30 |
| 31 #define MAX_LOWMEMORYKILL_TIME_SECS 30 |
| 32 #define UMA_HISTOGRAM_LOWMEMORYKILL_TIMES(name, sample) \ |
| 33 UMA_HISTOGRAM_CUSTOM_TIMES( \ |
| 34 name, sample, base::TimeDelta::FromMilliseconds(1), \ |
| 35 base::TimeDelta::FromSeconds(MAX_LOWMEMORYKILL_TIME_SECS), 50) |
| 36 |
| 37 ArcLowMemoryKillerMonitor::ArcLowMemoryKillerMonitor() |
| 38 : worker_pool_( |
| 39 new SequencedWorkerPool(1, "arc_low_memory_killer_monitor")) {} |
| 40 |
| 41 ArcLowMemoryKillerMonitor::~ArcLowMemoryKillerMonitor() { |
| 42 Stop(); |
| 43 } |
| 44 |
| 45 void ArcLowMemoryKillerMonitor::Start() { |
| 46 auto task_runner = worker_pool_->GetTaskRunnerWithShutdownBehavior( |
| 47 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); |
| 48 task_runner->PostTask( |
| 49 FROM_HERE, base::Bind(&ArcLowMemoryKillerMonitor::Run, worker_pool_)); |
| 50 } |
| 51 |
| 52 void ArcLowMemoryKillerMonitor::Stop() { |
| 53 worker_pool_->Shutdown(); |
| 54 } |
| 55 |
| 56 // static |
| 57 void ArcLowMemoryKillerMonitor::Run( |
| 58 scoped_refptr<base::SequencedWorkerPool> worker_pool) { |
| 59 static const int kMaxBufSize = 512; |
| 60 |
| 61 FILE* kmsg_handle = base::OpenFile(base::FilePath("/dev/kmsg"), "r"); |
| 62 if (!kmsg_handle) { |
| 63 LOG(WARNING) << "Open /dev/kmsg failed: " << base::safe_strerror(errno); |
| 64 return; |
| 65 } |
| 66 // Skip kernel messages prior to the instantiation of this object to avoid |
| 67 // double reporting. |
| 68 fseek(kmsg_handle, 0, SEEK_END); |
| 69 |
| 70 char buf[kMaxBufSize]; |
| 71 int freed_size; |
| 72 int64_t timestamp, last_timestamp = -1; |
| 73 const TimeDelta kMaxTimeDelta = |
| 74 TimeDelta::FromSeconds(MAX_LOWMEMORYKILL_TIME_SECS); |
| 75 |
| 76 while (fgets(buf, kMaxBufSize, kmsg_handle)) { |
| 77 if (worker_pool->IsShutdownInProgress()) { |
| 78 DVLOG(1) << "Chrome is shutting down, exit now."; |
| 79 break; |
| 80 } |
| 81 if (RE2::PartialMatch(buf, "lowmemorykiller: .* to free (\\d+)kB", |
| 82 &freed_size)) { |
| 83 std::vector<StringPiece> fields = SplitStringPiece( |
| 84 buf, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| 85 |
| 86 // The time to last kill event. Could be |kMaxTimeDelta| in case of the |
| 87 // first kill event. |
| 88 TimeDelta time_delta(kMaxTimeDelta); |
| 89 // Timestamp is the third field in a line of /dev/kmsg. |
| 90 // |
| 91 // Sample log line: |
| 92 // 6,2302,533604004,-;lowmemorykiller: Killing 'externalstorage' (21742), |
| 93 // adj 1000,\x0a to free 27320kB on behalf of 'kswapd0' (47) because\x0a |
| 94 // cache 181920kB is below limit 184320kB for oom_score_adj 1000\x0a |
| 95 // Free memory is 1228kB above reserved |
| 96 if (fields.size() >= 3) { |
| 97 base::StringToInt64(fields[2], ×tamp); |
| 98 if (last_timestamp > 0) { |
| 99 time_delta = TimeDelta::FromMicroseconds(timestamp - last_timestamp); |
| 100 } |
| 101 last_timestamp = timestamp; |
| 102 |
| 103 UMA_HISTOGRAM_MEMORY_KB("ArcRuntime.LowMemoryKiller.FreedSize", |
| 104 freed_size); |
| 105 UMA_HISTOGRAM_LOWMEMORYKILL_TIMES( |
| 106 "ArcRuntime.LowMemoryKiller.TimeDelta", time_delta); |
| 107 } |
| 108 } |
| 109 } |
| 110 base::CloseFile(kmsg_handle); |
| 111 } |
| 112 |
| 113 } // namespace arc |
OLD | NEW |