| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chromecast/browser/cast_memory_pressure_monitor.h" | 5 #include "chromecast/browser/cast_memory_pressure_monitor.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/process/process_metrics.h" | 13 #include "base/process/process_metrics.h" |
| 14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/threading/thread_task_runner_handle.h" | 15 #include "base/threading/thread_task_runner_handle.h" |
| 16 #include "chromecast/base/chromecast_switches.h" | 16 #include "chromecast/base/chromecast_switches.h" |
| 17 #include "chromecast/base/metrics/cast_metrics_helper.h" | 17 #include "chromecast/base/metrics/cast_metrics_helper.h" |
| 18 | 18 |
| 19 namespace chromecast { | 19 namespace chromecast { |
| 20 namespace { | 20 namespace { |
| 21 | 21 |
| 22 // Memory thresholds (as fraction of total memory) for memory pressure levels. | 22 // Memory thresholds (as fraction of total memory) for memory pressure levels. |
| 23 // See more detailed description of pressure heuristic in PollPressureLevel. | 23 // See more detailed description of pressure heuristic in PollPressureLevel. |
| 24 // TODO(halliwell): tune thresholds based on data. | 24 // TODO(halliwell): tune thresholds based on data. |
| 25 constexpr float kCriticalMemoryFraction = 0.2f; | 25 constexpr float kCriticalMemoryFraction = 0.25f; |
| 26 constexpr float kModerateMemoryFraction = 0.3f; | 26 constexpr float kModerateMemoryFraction = 0.4f; |
| 27 | 27 |
| 28 // Memory thresholds in MB for the simple heuristic based on 'free' memory. | 28 // Memory thresholds in MB for the simple heuristic based on 'free' memory. |
| 29 constexpr int kCriticalFreeMemoryKB = 20 * 1024; | 29 constexpr int kCriticalFreeMemoryKB = 20 * 1024; |
| 30 constexpr int kModerateFreeMemoryKB = 30 * 1024; | 30 constexpr int kModerateFreeMemoryKB = 30 * 1024; |
| 31 | 31 |
| 32 constexpr int kPollingIntervalMS = 5000; | 32 constexpr int kPollingIntervalMS = 5000; |
| 33 | 33 |
| 34 int GetSystemReservedKb() { | 34 int GetSystemReservedKb() { |
| 35 int rtn_kb_ = 0; | 35 int rtn_kb_ = 0; |
| 36 const base::CommandLine* command_line(base::CommandLine::ForCurrentProcess()); | 36 const base::CommandLine* command_line(base::CommandLine::ForCurrentProcess()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 60 } | 60 } |
| 61 | 61 |
| 62 void CastMemoryPressureMonitor::PollPressureLevel() { | 62 void CastMemoryPressureMonitor::PollPressureLevel() { |
| 63 MemoryPressureLevel level = | 63 MemoryPressureLevel level = |
| 64 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; | 64 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; |
| 65 | 65 |
| 66 base::SystemMemoryInfoKB info; | 66 base::SystemMemoryInfoKB info; |
| 67 if (!base::GetSystemMemoryInfo(&info)) { | 67 if (!base::GetSystemMemoryInfo(&info)) { |
| 68 LOG(ERROR) << "GetSystemMemoryInfo failed"; | 68 LOG(ERROR) << "GetSystemMemoryInfo failed"; |
| 69 } else { | 69 } else { |
| 70 if (system_reserved_kb_ == 0) { | 70 if (system_reserved_kb_ != 0 || info.available != 0) { |
| 71 // System reserved memory not configured: we have no idea how much of | 71 // Preferred memory pressure heuristic: |
| 72 // buffers+cached is safe to treat as usable, so use a simple heuristic | 72 // 1. Use /proc/meminfo's MemAvailable if possible, fall back to estimate |
| 73 // based purely on 'free' memory. | 73 // of free + buffers + cached otherwise. |
| 74 const int total_available = |
| 75 (info.available != 0) ? info.available |
| 76 : (info.free + info.buffers + info.cached); |
| 77 |
| 78 // 2. Allow some memory to be 'reserved' on command line. |
| 79 const int available = total_available - system_reserved_kb_; |
| 80 const int total = info.total - system_reserved_kb_; |
| 81 DCHECK_GT(total, 0); |
| 82 const float ratio = available / static_cast<float>(total); |
| 83 |
| 84 if (ratio < kCriticalMemoryFraction) |
| 85 level = base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; |
| 86 else if (ratio < kModerateMemoryFraction) |
| 87 level = base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; |
| 88 } else { |
| 89 // Backup method purely using 'free' memory. It may generate more |
| 90 // pressure events than necessary, since more memory may actually be free. |
| 74 if (info.free < kCriticalFreeMemoryKB) | 91 if (info.free < kCriticalFreeMemoryKB) |
| 75 level = base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; | 92 level = base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; |
| 76 else if (info.free < kModerateFreeMemoryKB) | 93 else if (info.free < kModerateFreeMemoryKB) |
| 77 level = base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; | 94 level = base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; |
| 78 } else { | |
| 79 // Platform has configured the 'reserved' memory; treat buffers plus | |
| 80 // cached minus reserved as available. | |
| 81 const float max_free = | |
| 82 info.free + info.buffers + info.cached - system_reserved_kb_; | |
| 83 const float total = info.total - system_reserved_kb_; | |
| 84 DCHECK(total > 0); | |
| 85 | |
| 86 if ((max_free / total) < kCriticalMemoryFraction) | |
| 87 level = base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; | |
| 88 else if ((max_free / total) < kModerateMemoryFraction) | |
| 89 level = base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; | |
| 90 } | 95 } |
| 91 } | 96 } |
| 92 | 97 |
| 93 UpdateMemoryPressureLevel(level); | 98 UpdateMemoryPressureLevel(level); |
| 94 | 99 |
| 95 UMA_HISTOGRAM_PERCENTAGE("Platform.MeminfoMemFree", | 100 UMA_HISTOGRAM_PERCENTAGE("Platform.MeminfoMemFree", |
| 96 (info.free * 100.0) / info.total); | 101 (info.free * 100.0) / info.total); |
| 97 UMA_HISTOGRAM_CUSTOM_COUNTS("Platform.Cast.MeminfoMemFreeDerived", | 102 UMA_HISTOGRAM_CUSTOM_COUNTS("Platform.Cast.MeminfoMemFreeDerived", |
| 98 (info.free + info.buffers + info.cached) / 1024, | 103 (info.free + info.buffers + info.cached) / 1024, |
| 99 1, 500, 100); | 104 1, 500, 100); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 122 metrics::CastMetricsHelper::GetInstance()->RecordApplicationEventWithValue( | 127 metrics::CastMetricsHelper::GetInstance()->RecordApplicationEventWithValue( |
| 123 "Memory.Pressure.LevelChange", new_level); | 128 "Memory.Pressure.LevelChange", new_level); |
| 124 } | 129 } |
| 125 | 130 |
| 126 void CastMemoryPressureMonitor::SetDispatchCallback( | 131 void CastMemoryPressureMonitor::SetDispatchCallback( |
| 127 const DispatchCallback& callback) { | 132 const DispatchCallback& callback) { |
| 128 dispatch_callback_ = callback; | 133 dispatch_callback_ = callback; |
| 129 } | 134 } |
| 130 | 135 |
| 131 } // namespace chromecast | 136 } // namespace chromecast |
| OLD | NEW |