blob: e5c832a1e71aa87aef19e197c5ede2917d71fcd3 [file] [log] [blame]
Honglin Yu1cd25072019-07-09 11:54:14 +10001// Copyright 2019 The Chromium OS 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 "ml/util.h"
6
7#include <string>
8#include <vector>
9
10#include <base/strings/string_number_conversions.h>
11#include <base/strings/string_split.h>
12#include <base/strings/string_util.h>
13#include <base/files/file_util.h>
14#include <base/process/process.h>
15
16namespace ml {
17
18namespace {
19
20// Extracts the value from a value string of /proc/[pid]/status.
21// Only works for value strings in the form of "value kB".
22// Returns true if value could be extracted, false otherwise.
23bool GetValueFromProcStatusValueStr(const std::string& value_str,
24 size_t* value) {
25 const std::vector<base::StringPiece> split_value_str = base::SplitStringPiece(
26 value_str, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
27
28 if (split_value_str.size() != 2 || split_value_str[1] != "kB")
29 return false;
30
31 return StringToSizeT(split_value_str[0], value);
32}
33
34} // namespace
35
36bool MemoryUsage::operator==(const MemoryUsage& other) const {
37 return this->VmRSSKb == other.VmRSSKb && this->VmSwapKb == other.VmSwapKb;
38}
39
40bool GetProcessMemoryUsageFromFile(MemoryUsage* memory_usage,
41 const base::FilePath& file_path) {
42 std::string status_data;
43 if (!ReadFileToString(file_path, &status_data)) {
44 LOG(WARNING) << "Can not open status file";
45 return false;
46 }
47
48 base::StringPairs key_value_pairs;
49 base::SplitStringIntoKeyValuePairs(status_data, ':', '\n', &key_value_pairs);
50
51 bool vmrss_found = false;
52 bool vmswap_found = false;
53
54 for (auto& pair : key_value_pairs) {
55 std::string& key = pair.first;
56 std::string& value_str = pair.second;
57
58 base::TrimWhitespaceASCII(key, base::TRIM_ALL, &key);
59
60 if (key == "VmRSS") {
61 if (vmrss_found)
62 return false; // Duplicates should not happen.
63
64 base::TrimWhitespaceASCII(value_str, base::TRIM_ALL, &value_str);
65 if (!GetValueFromProcStatusValueStr(value_str, &memory_usage->VmRSSKb))
66 return false;
67 vmrss_found = true;
68 }
69 if (key == "VmSwap") {
70 if (vmswap_found)
71 return false; // Duplicates should not happen.
72
73 base::TrimWhitespaceASCII(value_str, base::TRIM_ALL, &value_str);
74 if (!GetValueFromProcStatusValueStr(value_str, &memory_usage->VmSwapKb))
75 return false;
76 vmswap_found = true;
77 }
78 }
79
80 return vmrss_found && vmswap_found;
81}
82
Honglin Yu7b6c1192020-09-16 10:07:17 +100083bool GetProcessMemoryUsage(MemoryUsage* memory_usage, pid_t pid) {
84 const base::FilePath status_file_path = base::FilePath("/proc")
85 .Append(base::NumberToString(pid))
86 .Append("status");
Honglin Yu1cd25072019-07-09 11:54:14 +100087 return GetProcessMemoryUsageFromFile(memory_usage, status_file_path);
88}
89
Honglin Yu7b6c1192020-09-16 10:07:17 +100090bool GetProcessMemoryUsage(MemoryUsage* memory_usage) {
91 return GetProcessMemoryUsage(memory_usage, base::Process::Current().Pid());
92}
93
Honglin Yu1cd25072019-07-09 11:54:14 +100094bool GetTotalProcessMemoryUsage(size_t* total_memory) {
95 MemoryUsage memory_usage;
96 if (GetProcessMemoryUsage(&memory_usage)) {
97 *total_memory = memory_usage.VmRSSKb + memory_usage.VmSwapKb;
98 return true;
99 }
100 return false;
101}
102
103} // namespace ml