| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "components/tracing/common/process_metrics_memory_dump_provider.h" | 5 #include "components/tracing/common/process_metrics_memory_dump_provider.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| 11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
| 12 #include "base/memory/ptr_util.h" |
| 13 #include "base/process/process_metrics.h" |
| 12 #include "base/trace_event/process_memory_dump.h" | 14 #include "base/trace_event/process_memory_dump.h" |
| 13 #include "base/trace_event/process_memory_maps.h" | 15 #include "base/trace_event/process_memory_maps.h" |
| 14 #include "base/trace_event/process_memory_totals.h" | 16 #include "base/trace_event/process_memory_totals.h" |
| 15 #include "base/trace_event/trace_event_argument.h" | 17 #include "base/trace_event/trace_event_argument.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 17 | 19 |
| 18 namespace tracing { | 20 namespace tracing { |
| 19 | 21 |
| 20 #if defined(OS_LINUX) || defined(OS_ANDROID) | 22 #if defined(OS_LINUX) || defined(OS_ANDROID) |
| 21 namespace { | 23 namespace { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 "Private_Dirty: 4 kB\n" | 102 "Private_Dirty: 4 kB\n" |
| 101 "Referenced: 40 kB\n" | 103 "Referenced: 40 kB\n" |
| 102 "Anonymous: 16 kB\n" | 104 "Anonymous: 16 kB\n" |
| 103 "AnonHugePages: 0 kB\n" | 105 "AnonHugePages: 0 kB\n" |
| 104 "Swap: 0 kB\n" | 106 "Swap: 0 kB\n" |
| 105 "KernelPageSize: 4 kB\n" | 107 "KernelPageSize: 4 kB\n" |
| 106 "MMUPageSize: 4 kB\n" | 108 "MMUPageSize: 4 kB\n" |
| 107 "Locked: 0 kB\n" | 109 "Locked: 0 kB\n" |
| 108 "VmFlags: rd wr mr mw me ac sd\n"; | 110 "VmFlags: rd wr mr mw me ac sd\n"; |
| 109 | 111 |
| 110 void CreateAndSetSmapsFileForTesting(const char* smaps_string, | 112 const char kTestStatm[] = "200 100 20 2 3 4"; |
| 111 base::ScopedFILE& file) { | 113 |
| 114 void CreateTempFileWithContents(const char* contents, base::ScopedFILE* file) { |
| 112 base::FilePath temp_path; | 115 base::FilePath temp_path; |
| 113 FILE* temp_file = CreateAndOpenTemporaryFile(&temp_path); | 116 FILE* temp_file = CreateAndOpenTemporaryFile(&temp_path); |
| 114 file.reset(temp_file); | 117 file->reset(temp_file); |
| 115 ASSERT_TRUE(temp_file); | 118 ASSERT_TRUE(temp_file); |
| 116 | 119 |
| 117 ASSERT_TRUE(base::WriteFileDescriptor(fileno(temp_file), smaps_string, | 120 ASSERT_TRUE( |
| 118 strlen(smaps_string))); | 121 base::WriteFileDescriptor(fileno(temp_file), contents, strlen(contents))); |
| 119 } | 122 } |
| 120 | 123 |
| 121 } // namespace | 124 } // namespace |
| 122 #endif // defined(OS_LINUX) || defined(OS_ANDROID) | 125 #endif // defined(OS_LINUX) || defined(OS_ANDROID) |
| 123 | 126 |
| 124 TEST(ProcessMetricsMemoryDumpProviderTest, DumpRSS) { | 127 TEST(ProcessMetricsMemoryDumpProviderTest, DumpRSS) { |
| 125 const base::trace_event::MemoryDumpArgs high_detail_args = { | 128 const base::trace_event::MemoryDumpArgs high_detail_args = { |
| 126 base::trace_event::MemoryDumpLevelOfDetail::DETAILED}; | 129 base::trace_event::MemoryDumpLevelOfDetail::DETAILED}; |
| 127 std::unique_ptr<ProcessMetricsMemoryDumpProvider> pmtdp( | 130 std::unique_ptr<ProcessMetricsMemoryDumpProvider> pmtdp( |
| 128 new ProcessMetricsMemoryDumpProvider(base::kNullProcessId)); | 131 new ProcessMetricsMemoryDumpProvider(base::kNullProcessId)); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 base::ScopedFILE empty_file(OpenFile(base::FilePath("/dev/null"), "r")); | 178 base::ScopedFILE empty_file(OpenFile(base::FilePath("/dev/null"), "r")); |
| 176 ASSERT_TRUE(empty_file.get()); | 179 ASSERT_TRUE(empty_file.get()); |
| 177 ProcessMetricsMemoryDumpProvider::proc_smaps_for_testing = empty_file.get(); | 180 ProcessMetricsMemoryDumpProvider::proc_smaps_for_testing = empty_file.get(); |
| 178 pmmdp->OnMemoryDump(dump_args, &pmd_invalid); | 181 pmmdp->OnMemoryDump(dump_args, &pmd_invalid); |
| 179 ASSERT_FALSE(pmd_invalid.has_process_mmaps()); | 182 ASSERT_FALSE(pmd_invalid.has_process_mmaps()); |
| 180 | 183 |
| 181 // Parse the 1st smaps file. | 184 // Parse the 1st smaps file. |
| 182 base::trace_event::ProcessMemoryDump pmd_1(nullptr /* session_state */, | 185 base::trace_event::ProcessMemoryDump pmd_1(nullptr /* session_state */, |
| 183 dump_args); | 186 dump_args); |
| 184 base::ScopedFILE temp_file1; | 187 base::ScopedFILE temp_file1; |
| 185 CreateAndSetSmapsFileForTesting(kTestSmaps1, temp_file1); | 188 CreateTempFileWithContents(kTestSmaps1, &temp_file1); |
| 186 ProcessMetricsMemoryDumpProvider::proc_smaps_for_testing = temp_file1.get(); | 189 ProcessMetricsMemoryDumpProvider::proc_smaps_for_testing = temp_file1.get(); |
| 187 pmmdp->OnMemoryDump(dump_args, &pmd_1); | 190 pmmdp->OnMemoryDump(dump_args, &pmd_1); |
| 188 ASSERT_TRUE(pmd_1.has_process_mmaps()); | 191 ASSERT_TRUE(pmd_1.has_process_mmaps()); |
| 189 const auto& regions_1 = pmd_1.process_mmaps()->vm_regions(); | 192 const auto& regions_1 = pmd_1.process_mmaps()->vm_regions(); |
| 190 ASSERT_EQ(2UL, regions_1.size()); | 193 ASSERT_EQ(2UL, regions_1.size()); |
| 191 | 194 |
| 192 EXPECT_EQ(0x00400000UL, regions_1[0].start_address); | 195 EXPECT_EQ(0x00400000UL, regions_1[0].start_address); |
| 193 EXPECT_EQ(0x004be000UL - 0x00400000UL, regions_1[0].size_in_bytes); | 196 EXPECT_EQ(0x004be000UL - 0x00400000UL, regions_1[0].size_in_bytes); |
| 194 EXPECT_EQ(kProtR | kProtX, regions_1[0].protection_flags); | 197 EXPECT_EQ(kProtR | kProtX, regions_1[0].protection_flags); |
| 195 EXPECT_EQ("/file/1", regions_1[0].mapped_file); | 198 EXPECT_EQ("/file/1", regions_1[0].mapped_file); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 208 EXPECT_EQ(120 * 1024UL, regions_1[1].byte_stats_shared_clean_resident); | 211 EXPECT_EQ(120 * 1024UL, regions_1[1].byte_stats_shared_clean_resident); |
| 209 EXPECT_EQ(4 * 1024UL, regions_1[1].byte_stats_shared_dirty_resident); | 212 EXPECT_EQ(4 * 1024UL, regions_1[1].byte_stats_shared_dirty_resident); |
| 210 EXPECT_EQ(60 * 1024UL, regions_1[1].byte_stats_private_clean_resident); | 213 EXPECT_EQ(60 * 1024UL, regions_1[1].byte_stats_private_clean_resident); |
| 211 EXPECT_EQ(8 * 1024UL, regions_1[1].byte_stats_private_dirty_resident); | 214 EXPECT_EQ(8 * 1024UL, regions_1[1].byte_stats_private_dirty_resident); |
| 212 EXPECT_EQ(0 * 1024UL, regions_1[1].byte_stats_swapped); | 215 EXPECT_EQ(0 * 1024UL, regions_1[1].byte_stats_swapped); |
| 213 | 216 |
| 214 // Parse the 2nd smaps file. | 217 // Parse the 2nd smaps file. |
| 215 base::trace_event::ProcessMemoryDump pmd_2(nullptr /* session_state */, | 218 base::trace_event::ProcessMemoryDump pmd_2(nullptr /* session_state */, |
| 216 dump_args); | 219 dump_args); |
| 217 base::ScopedFILE temp_file2; | 220 base::ScopedFILE temp_file2; |
| 218 CreateAndSetSmapsFileForTesting(kTestSmaps2, temp_file2); | 221 CreateTempFileWithContents(kTestSmaps2, &temp_file2); |
| 219 ProcessMetricsMemoryDumpProvider::proc_smaps_for_testing = temp_file2.get(); | 222 ProcessMetricsMemoryDumpProvider::proc_smaps_for_testing = temp_file2.get(); |
| 220 pmmdp->OnMemoryDump(dump_args, &pmd_2); | 223 pmmdp->OnMemoryDump(dump_args, &pmd_2); |
| 221 ASSERT_TRUE(pmd_2.has_process_mmaps()); | 224 ASSERT_TRUE(pmd_2.has_process_mmaps()); |
| 222 const auto& regions_2 = pmd_2.process_mmaps()->vm_regions(); | 225 const auto& regions_2 = pmd_2.process_mmaps()->vm_regions(); |
| 223 ASSERT_EQ(1UL, regions_2.size()); | 226 ASSERT_EQ(1UL, regions_2.size()); |
| 224 EXPECT_EQ(0x7fe7ce79c000UL, regions_2[0].start_address); | 227 EXPECT_EQ(0x7fe7ce79c000UL, regions_2[0].start_address); |
| 225 EXPECT_EQ(0x7fe7ce7a8000UL - 0x7fe7ce79c000UL, regions_2[0].size_in_bytes); | 228 EXPECT_EQ(0x7fe7ce7a8000UL - 0x7fe7ce79c000UL, regions_2[0].size_in_bytes); |
| 226 EXPECT_EQ(0U, regions_2[0].protection_flags); | 229 EXPECT_EQ(0U, regions_2[0].protection_flags); |
| 227 EXPECT_EQ("", regions_2[0].mapped_file); | 230 EXPECT_EQ("", regions_2[0].mapped_file); |
| 228 EXPECT_EQ(32 * 1024UL, regions_2[0].byte_stats_proportional_resident); | 231 EXPECT_EQ(32 * 1024UL, regions_2[0].byte_stats_proportional_resident); |
| 229 EXPECT_EQ(16 * 1024UL, regions_2[0].byte_stats_shared_clean_resident); | 232 EXPECT_EQ(16 * 1024UL, regions_2[0].byte_stats_shared_clean_resident); |
| 230 EXPECT_EQ(12 * 1024UL, regions_2[0].byte_stats_shared_dirty_resident); | 233 EXPECT_EQ(12 * 1024UL, regions_2[0].byte_stats_shared_dirty_resident); |
| 231 EXPECT_EQ(8 * 1024UL, regions_2[0].byte_stats_private_clean_resident); | 234 EXPECT_EQ(8 * 1024UL, regions_2[0].byte_stats_private_clean_resident); |
| 232 EXPECT_EQ(4 * 1024UL, regions_2[0].byte_stats_private_dirty_resident); | 235 EXPECT_EQ(4 * 1024UL, regions_2[0].byte_stats_private_dirty_resident); |
| 233 EXPECT_EQ(0 * 1024UL, regions_2[0].byte_stats_swapped); | 236 EXPECT_EQ(0 * 1024UL, regions_2[0].byte_stats_swapped); |
| 234 } | 237 } |
| 235 #endif // defined(OS_LINUX) || defined(OS_ANDROID) | 238 #endif // defined(OS_LINUX) || defined(OS_ANDROID) |
| 236 | 239 |
| 240 TEST(ProcessMetricsMemoryDumpProviderTest, TestPollFastMemoryTotal) { |
| 241 ProcessMetricsMemoryDumpProvider mdp(base::kNullProcessId); |
| 242 |
| 243 uint64_t total1, total2; |
| 244 mdp.PollFastMemoryTotal(&total1); |
| 245 ASSERT_GT(total1, 0u); |
| 246 size_t kBufSize = 16 * 1024 * 1024; |
| 247 auto buf = base::MakeUnique<char[]>(kBufSize); |
| 248 for (size_t i = 0; i < kBufSize; i++) |
| 249 buf[i] = *((volatile char*)&buf[i]) + 1; |
| 250 mdp.PollFastMemoryTotal(&total2); |
| 251 ASSERT_GT(total2, 0u); |
| 252 EXPECT_GT(total2, total1 + kBufSize / 2); |
| 253 |
| 254 #if defined(OS_LINUX) || defined(OS_ANDROID) |
| 255 EXPECT_GE(mdp.fast_polling_statm_fd_.get(), 0); |
| 256 |
| 257 base::ScopedFILE temp_file; |
| 258 CreateTempFileWithContents(kTestStatm, &temp_file); |
| 259 mdp.fast_polling_statm_fd_for_testing = fileno(temp_file.get()); |
| 260 size_t page_size = base::GetPageSize(); |
| 261 uint64_t value; |
| 262 mdp.PollFastMemoryTotal(&value); |
| 263 EXPECT_EQ(100 * page_size, value); |
| 264 |
| 265 mdp.SuspendFastMemoryPolling(); |
| 266 EXPECT_FALSE(mdp.fast_polling_statm_fd_.is_valid()); |
| 267 #else |
| 268 mdp.SuspendFastMemoryPolling(); |
| 269 #endif |
| 270 } |
| 271 |
| 237 } // namespace tracing | 272 } // namespace tracing |
| OLD | NEW |