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 |