Chromium Code Reviews| 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 <fcntl.h> | |
| 8 #include <vector> | |
| 9 | |
| 10 #include "base/bind.h" | |
| 11 #include "base/location.h" | |
| 12 #include "base/logging.h" | |
| 13 #include "base/metrics/histogram_macros.h" | |
| 14 #include "base/sequenced_task_runner.h" | |
| 15 #include "base/strings/string_number_conversions.h" | |
| 16 #include "base/strings/string_split.h" | |
| 17 #include "base/time/time.h" | |
| 18 #include "third_party/re2/src/re2/re2.h" | |
| 19 | |
| 20 namespace arc { | |
| 21 | |
| 22 using base::SequencedWorkerPool; | |
| 23 using base::StringPiece; | |
| 24 using base::TimeDelta; | |
| 25 | |
| 26 #define MAX_LOWMEMORYKILL_TIME_SECS 30 | |
| 27 #define UMA_HISTOGRAM_LOWMEMORYKILL_TIMES(name, sample) \ | |
| 28 UMA_HISTOGRAM_CUSTOM_TIMES( \ | |
| 29 name, sample, base::TimeDelta::FromMilliseconds(1), \ | |
| 30 base::TimeDelta::FromSeconds(MAX_LOWMEMORYKILL_TIME_SECS), 50) | |
| 31 | |
| 32 ArcLowMemoryKillerMonitor::ArcLowMemoryKillerMonitor() | |
| 33 : worker_pool_( | |
| 34 new SequencedWorkerPool(1, "arc_low_memory_killer_monitor")), | |
| 35 weak_ptr_factory_(this) {} | |
| 36 | |
| 37 ArcLowMemoryKillerMonitor::~ArcLowMemoryKillerMonitor() { | |
| 38 Stop(); | |
| 39 } | |
| 40 | |
| 41 void ArcLowMemoryKillerMonitor::Start() { | |
| 42 auto task_runner = worker_pool_->GetTaskRunnerWithShutdownBehavior( | |
| 43 SequencedWorkerPool::CONTINUE_ON_SHUTDOWN); | |
| 44 task_runner->PostTask( | |
| 45 FROM_HERE, | |
| 46 base::Bind(&ArcLowMemoryKillerMonitor::Run, | |
| 47 weak_ptr_factory_.GetWeakPtr())); | |
| 48 } | |
| 49 | |
| 50 void ArcLowMemoryKillerMonitor::Stop() { | |
| 51 worker_pool_->Shutdown(); | |
| 52 } | |
| 53 | |
| 54 void ArcLowMemoryKillerMonitor::Run() { | |
| 55 // Keep a reference to worker_pool_ in case |this| is deleted in | |
| 56 // shutdown process while this thread returns from a blocking read. | |
| 57 scoped_refptr<SequencedWorkerPool> worker_pool(worker_pool_); | |
|
Yusuke Sato
2016/03/14 18:02:12
please remove this and modify the Bind code if you
cylee1
2016/03/15 12:49:15
Done.
| |
| 58 | |
| 59 static const int kMaxBufSize = 512; | |
| 60 | |
| 61 FILE* kmsg_handle = fopen("/dev/kmsg", "r"); | |
|
Yusuke Sato
2016/03/14 18:02:12
If you really want to go with FILE, that's fine, b
cylee1
2016/03/15 12:49:15
Ah sorry I'm not familiar with base/files so misse
| |
| 62 char buf[kMaxBufSize]; | |
| 63 int freed_size; | |
| 64 int64_t timestamp, last_timestamp = -1; | |
| 65 const TimeDelta kMaxTimeDelta = TimeDelta::FromSeconds( | |
| 66 MAX_LOWMEMORYKILL_TIME_SECS); | |
| 67 | |
| 68 int kmsg_fd = fileno(kmsg_handle); | |
| 69 int flags = fcntl(kmsg_fd, F_GETFL, 0); | |
| 70 // Consume kernel messages prior to the instantiation of this object to avoid | |
| 71 // double reporting. | |
| 72 fcntl(kmsg_fd, F_SETFL, flags | O_NONBLOCK); | |
|
Yusuke Sato
2016/03/14 18:02:12
SetNonBlocking()
cylee1
2016/03/15 12:49:15
Done.
| |
| 73 while (fgets(buf, kMaxBufSize, kmsg_handle)) {} | |
|
Yusuke Sato
2016/03/14 18:02:12
The code (setting O_NONBLOCK to the underlying fd,
cylee1
2016/03/15 12:49:15
fseek is better, I missed it.
I can't use the time
| |
| 74 | |
| 75 // Switch back to blocking read. | |
| 76 fcntl(kmsg_fd, F_SETFL, flags & ~O_NONBLOCK); | |
|
Yusuke Sato
2016/03/14 18:02:12
same
cylee1
2016/03/15 12:49:15
Done.
| |
| 77 | |
| 78 while (fgets(buf, kMaxBufSize, kmsg_handle)) { | |
| 79 if (worker_pool->IsShutdownInProgress()) { | |
| 80 LOG(WARNING) << "Chrome is shutting down, exit now."; | |
| 81 break; | |
| 82 } | |
| 83 if (RE2::PartialMatch(buf, | |
| 84 "lowmemorykiller: .* to free (\\d+)kB", | |
| 85 &freed_size)) { | |
| 86 std::vector<StringPiece> fields = SplitStringPiece( | |
| 87 buf, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 88 | |
| 89 // The time to last kill event. Could be |kMaxTimeDelta| in case of the | |
| 90 // first kill event. | |
| 91 TimeDelta time_delta(kMaxTimeDelta); | |
| 92 // Timestamp is the third field in a line of /dev/kmsg. | |
| 93 // | |
| 94 // Sample log line: | |
| 95 // 6,2302,533604004,-;lowmemorykiller: Killing 'externalstorage' (21742), | |
| 96 // adj 1000,\x0a to free 27320kB on behalf of 'kswapd0' (47) because\x0a | |
| 97 // cache 181920kB is below limit 184320kB for oom_score_adj 1000\x0a | |
| 98 // Free memory is 1228kB above reserved | |
| 99 if (fields.size() >= 3) { | |
| 100 base::StringToInt64(fields[2], ×tamp); | |
| 101 if (last_timestamp > 0) { | |
| 102 time_delta = TimeDelta::FromMicroseconds(timestamp - last_timestamp); | |
| 103 } | |
| 104 last_timestamp = timestamp; | |
| 105 | |
| 106 UMA_HISTOGRAM_MEMORY_KB( | |
| 107 "ArcRuntime.LowMemoryKiller.FreedSize", freed_size); | |
| 108 UMA_HISTOGRAM_LOWMEMORYKILL_TIMES( | |
| 109 "ArcRuntime.LowMemoryKiller.TimeDelta", time_delta); | |
| 110 } | |
| 111 } | |
| 112 } | |
| 113 fclose(kmsg_handle); | |
|
Yusuke Sato
2016/03/14 18:02:12
CloseFile()
cylee1
2016/03/15 18:26:57
Done.
| |
| 114 } | |
| 115 | |
| 116 } // namespace arc | |
| OLD | NEW |