Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(312)

Side by Side Diff: systrace/atrace_helper/jni/process_memory_stats.cc

Issue 2946033002: Android systrace: Optimize memory dumps. (Closed)
Patch Set: tiny fix Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 "process_memory_stats.h" 5 #include "process_memory_stats.h"
6 6
7 #include <stdio.h> 7 #include <stdio.h>
8 #include <stdlib.h> 8 #include <stdlib.h>
9 9
10 #include <memory> 10 #include <memory>
11 11
12 #include "file_utils.h" 12 #include "file_utils.h"
13 #include "libmemtrack_wrapper.h" 13 #include "libmemtrack_wrapper.h"
14 #include "logging.h" 14 #include "logging.h"
15 15
16 namespace { 16 namespace {
17 17
18 const int kKbPerPage = 4; 18 const int kKbPerPage = 4;
19 19
20 const char kRss[] = "Rss";
21 const char kPss[] = "Pss";
22 const char kSwap[] = "Swap";
23 const char kSharedClean[] = "Shared_Clean";
24 const char kSharedDirty[] = "Shared_Dirty";
25 const char kPrivateClean[] = "Private_Clean";
26 const char kPrivateDirty[] = "Private_Dirty";
27
20 // Takes a C string buffer and chunks it into lines without creating any 28 // Takes a C string buffer and chunks it into lines without creating any
21 // copies. It modifies the original buffer, by replacing \n with \0. 29 // copies. It modifies the original buffer, by replacing \n with \0.
22 class LineReader { 30 class LineReader {
23 public: 31 public:
24 LineReader(char* buf, size_t size) : ptr_(buf), end_(buf + size) {} 32 LineReader(char* buf, size_t size) : ptr_(buf), end_(buf + size) {}
25 33
26 const char* NextLine() { 34 const char* NextLine() {
27 if (ptr_ >= end_) 35 if (ptr_ >= end_)
28 return nullptr; 36 return nullptr;
29 const char* cur = ptr_; 37 const char* cur = ptr_;
30 char* next = strchr(ptr_, '\n'); 38 char* next = strchr(ptr_, '\n');
31 if (next) { 39 if (next) {
32 *next = '\0'; 40 *next = '\0';
33 ptr_ = next + 1; 41 ptr_ = next + 1;
34 } else { 42 } else {
35 ptr_ = end_; 43 ptr_ = end_;
36 } 44 }
37 return cur; 45 return cur;
38 } 46 }
39 47
40 private: 48 private:
41 char* ptr_; 49 char* ptr_;
42 char* end_; 50 char* end_;
43 }; 51 };
44 52
45 bool ReadSmapsMetric(const char* line, const char* metric, uint64_t* res) { 53 bool ReadSmapsMetric(
46 if (strncmp(line, metric, strlen(metric))) 54 const char* line, const char* metric, int metric_size, uint64_t* res) {
55 if (strncmp(line, metric, metric_size - 1))
47 return false; 56 return false;
48 line = strchr(line, ':'); 57 if (line[metric_size - 1] != ':')
49 if (!line)
50 return false; 58 return false;
51 *res = strtoull(line + 1, nullptr, 10); 59 *res = strtoull(line + metric_size, nullptr, 10);
52 return true; 60 return true;
53 } 61 }
54 62
55 } // namespace 63 } // namespace
56 64
57 ProcessMemoryStats::ProcessMemoryStats(int pid) : pid_(pid) {} 65 bool ProcessMemoryStats::ReadLightStats(int pid) {
58
59 bool ProcessMemoryStats::ReadLightStats() {
60 char buf[64]; 66 char buf[64];
61 if (file_utils::ReadProcFile(pid_, "statm", buf, sizeof(buf)) <= 0) 67 if (file_utils::ReadProcFile(pid, "statm", buf, sizeof(buf)) <= 0)
62 return false; 68 return false;
63 uint32_t vm_size_pages; 69 uint32_t vm_size_pages;
64 uint32_t rss_pages; 70 uint32_t rss_pages;
65 int res = sscanf(buf, "%u %u", &vm_size_pages, &rss_pages); 71 int res = sscanf(buf, "%u %u", &vm_size_pages, &rss_pages);
66 CHECK(res == 2); 72 CHECK(res == 2);
67 rss_kb_ = rss_pages * kKbPerPage; 73 rss_kb_ = rss_pages * kKbPerPage;
68 virt_kb_ = vm_size_pages * kKbPerPage; 74 virt_kb_ = vm_size_pages * kKbPerPage;
69 return true; 75 return true;
70 } 76 }
71 77
72 bool ProcessMemoryStats::ReadFullStats() { 78 bool ProcessMemoryStats::ReadFullStats(int pid) {
73 const size_t kBufSize = 32u * 1024 * 1024; 79 const size_t kBufSize = 8u * 1024 * 1024;
74 std::unique_ptr<char[]> buf(new char[kBufSize]); 80 std::unique_ptr<char[]> buf(new char[kBufSize]);
75 ssize_t rsize = file_utils::ReadProcFile(pid_, "smaps", &buf[0], kBufSize); 81 ssize_t rsize = file_utils::ReadProcFile(pid, "smaps", &buf[0], kBufSize);
76 if (rsize <= 0) 82 if (rsize <= 0)
77 return false; 83 return false;
78 MmapInfo* last_mmap_entry = nullptr; 84 MmapInfo* last_mmap_entry = nullptr;
79 std::unique_ptr<MmapInfo> new_mmap(new MmapInfo()); 85 std::unique_ptr<MmapInfo> new_mmap(new MmapInfo());
80 CHECK(mmaps_.empty()); 86 CHECK(mmaps_.empty());
81 CHECK(rss_kb_ == 0); 87 CHECK(rss_kb_ == 0);
82 88
83 // Iterate over all lines in /proc/PID/smaps. 89 // Iterate over all lines in /proc/PID/smaps.
84 LineReader rd(&buf[0], rsize); 90 LineReader rd(&buf[0], rsize);
85 for (const char* line = rd.NextLine(); line; line = rd.NextLine()) { 91 for (const char* line = rd.NextLine(); line; line = rd.NextLine()) {
86 // Check if the current line is the beginning of a new mmaps entry, e.g.: 92 if (!line[0])
87 // be7f7000-be818000 rw-p 00000000 00:00 0 [stack] 93 continue;
88 // Note that the mapped file name ([stack]) is optional and won't be 94 // Performance optimization (hack).
89 // present 95 // Any header line starts with lowercase hex digit but subsequent lines
90 // on anonymous memory maps (hence res >= 3 below). 96 // start with uppercase letter.
91 int res = sscanf( 97 if (line[0] < 'A' || line[0] > 'Z') {
92 line, "%llx-%llx %4s %*llx %*[:0-9a-f] %*[0-9a-f]%*[ \t]%128[^\n]", 98 // Note that the mapped file name ([stack]) is optional and won't be
93 &new_mmap->start_addr, &new_mmap->end_addr, new_mmap->prot_flags, 99 // present on anonymous memory maps (hence res >= 3 below).
94 new_mmap->mapped_file); 100 int res = sscanf(line,
95 if (res >= 3) { 101 "%llx-%llx %4s %*llx %*[:0-9a-f] %*[0-9a-f]%*[ \t]%127[^\n]",
102 &new_mmap->start_addr, &new_mmap->end_addr, new_mmap->prot_flags,
103 new_mmap->mapped_file);
96 last_mmap_entry = new_mmap.get(); 104 last_mmap_entry = new_mmap.get();
97 CHECK(new_mmap->end_addr >= new_mmap->start_addr); 105 CHECK(new_mmap->end_addr >= new_mmap->start_addr);
98 new_mmap->virt_kb = (new_mmap->end_addr - new_mmap->start_addr) / 1024; 106 new_mmap->virt_kb =
107 (new_mmap->end_addr - new_mmap->start_addr) / 1024;
99 if (res == 3) 108 if (res == 3)
100 new_mmap->mapped_file[0] = '\0'; 109 new_mmap->mapped_file[0] = '\0';
101 virt_kb_ += new_mmap->virt_kb; 110 virt_kb_ += new_mmap->virt_kb;
102 mmaps_[new_mmap->start_addr] = std::move(new_mmap); 111 mmaps_.push_back(std::move(new_mmap));
103 new_mmap.reset(new MmapInfo()); 112 new_mmap.reset(new MmapInfo());
104 } else { 113 } else {
105 // The current line is a metrics line within a mmap entry, e.g.: 114 // The current line is a metrics line within a mmap entry, e.g.:
106 // Size: 4 kB 115 // Size: 4 kB
107 uint64_t size = 0; 116 uint64_t size = 0;
108 CHECK(last_mmap_entry); 117 CHECK(last_mmap_entry);
109 if (ReadSmapsMetric(line, "Rss:", &size)) { 118 if (ReadSmapsMetric(line, kRss, sizeof(kRss), &size)) {
110 last_mmap_entry->rss_kb = size; 119 last_mmap_entry->rss_kb = size;
111 rss_kb_ += size; 120 rss_kb_ += size;
112 } else if (ReadSmapsMetric(line, "Pss:", &size)) { 121 } else if (ReadSmapsMetric(line, kPss, sizeof(kPss), &size)) {
113 last_mmap_entry->pss_kb = size; 122 last_mmap_entry->pss_kb = size;
114 pss_kb_ += size; 123 pss_kb_ += size;
115 } else if (ReadSmapsMetric(line, "Swap:", &size)) { 124 } else if (ReadSmapsMetric(line, kSwap, sizeof(kSwap), &size)) {
116 last_mmap_entry->swapped_kb = size; 125 last_mmap_entry->swapped_kb = size;
117 swapped_kb_ += size; 126 swapped_kb_ += size;
118 } else if (ReadSmapsMetric(line, "Shared_Clean:", &size)) { 127 } else if (ReadSmapsMetric(
128 line, kSharedClean, sizeof(kSharedClean), &size)) {
119 last_mmap_entry->shared_clean_kb = size; 129 last_mmap_entry->shared_clean_kb = size;
120 shared_clean_kb_ += size; 130 shared_clean_kb_ += size;
121 } else if (ReadSmapsMetric(line, "Shared_Dirty:", &size)) { 131 } else if (ReadSmapsMetric(
132 line, kSharedDirty, sizeof(kSharedDirty), &size)) {
122 last_mmap_entry->shared_dirty_kb = size; 133 last_mmap_entry->shared_dirty_kb = size;
123 shared_dirty_kb_ += size; 134 shared_dirty_kb_ += size;
124 } else if (ReadSmapsMetric(line, "Private_Clean:", &size)) { 135 } else if (ReadSmapsMetric(
136 line, kPrivateClean, sizeof(kPrivateClean), &size)) {
125 last_mmap_entry->private_clean_kb = size; 137 last_mmap_entry->private_clean_kb = size;
126 private_clean_kb_ += size; 138 private_clean_kb_ += size;
127 } else if (ReadSmapsMetric(line, "Private_Dirty:", &size)) { 139 } else if (ReadSmapsMetric(
140 line, kPrivateDirty, sizeof(kPrivateDirty), &size)) {
128 last_mmap_entry->private_dirty_kb = size; 141 last_mmap_entry->private_dirty_kb = size;
129 private_dirty_kb_ += size; 142 private_dirty_kb_ += size;
130 } 143 }
131 } 144 }
132 } 145 }
146 full_stats_ = true;
133 return true; 147 return true;
134 } 148 }
135 149
136 bool ProcessMemoryStats::ReadMemtrackStats() { 150 bool ProcessMemoryStats::ReadGpuStats(int pid) {
137 MemtrackProc mt(pid_); 151 MemtrackProc mt(pid);
138 gpu_graphics_kb_ = mt.graphics_total() / 1024; 152 gpu_graphics_kb_ = mt.graphics_total() / 1024;
139 gpu_graphics_pss_kb_ = mt.graphics_pss() / 1024; 153 gpu_graphics_pss_kb_ = mt.graphics_pss() / 1024;
140 gpu_gl_kb_ = mt.gl_total() / 1024; 154 gpu_gl_kb_ = mt.gl_total() / 1024;
141 gpu_gl_pss_kb_ = mt.gl_pss() / 1024; 155 gpu_gl_pss_kb_ = mt.gl_pss() / 1024;
142 gpu_other_kb_ = mt.other_total() / 1024; 156 gpu_other_kb_ = mt.other_total() / 1024;
143 gpu_other_pss_kb_ = mt.other_pss() / 1024; 157 gpu_other_pss_kb_ = mt.other_pss() / 1024;
144 return !mt.has_errors(); 158
159 gpu_stats_ = !mt.has_errors() &&
160 (gpu_graphics_kb_ != 0 || gpu_gl_kb_ != 0 || gpu_other_kb_ != 0);
161 return gpu_stats_;
145 } 162 }
OLDNEW
« no previous file with comments | « systrace/atrace_helper/jni/process_memory_stats.h ('k') | systrace/atrace_helper/jni/procfs_utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698