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 3 // found in the LICENSE file. 4 5 #include "base/trace_event/process_memory_totals_dump_provider.h" 6 7 #include <stddef.h> 8 9 #include "base/process/process_metrics.h" 10 #include "base/trace_event/process_memory_dump.h" 11 #include "base/trace_event/process_memory_totals.h" 12 #include "build/build_config.h" 13 14 #if defined(OS_LINUX) || defined(OS_ANDROID) 15 #include <fcntl.h> 16 17 #include "base/files/file_util.h" 18 19 namespace { 20 bool kernel_supports_rss_peak_reset = true; 21 const char kClearPeakRssCommand[] = "5"; 22 } 23 #endif 24 25 namespace base { 26 namespace trace_event { 27 28 // static 29 uint64_t ProcessMemoryTotalsDumpProvider::rss_bytes_for_testing = 0; 30 31 // static 32 ProcessMemoryTotalsDumpProvider* GetInstance()33ProcessMemoryTotalsDumpProvider::GetInstance() { 34 return Singleton< 35 ProcessMemoryTotalsDumpProvider, 36 LeakySingletonTraits<ProcessMemoryTotalsDumpProvider>>::get(); 37 } 38 ProcessMemoryTotalsDumpProvider()39ProcessMemoryTotalsDumpProvider::ProcessMemoryTotalsDumpProvider() 40 : process_metrics_(ProcessMetrics::CreateCurrentProcessMetrics()) {} 41 ~ProcessMemoryTotalsDumpProvider()42ProcessMemoryTotalsDumpProvider::~ProcessMemoryTotalsDumpProvider() { 43 } 44 45 // Called at trace dump point time. Creates a snapshot the memory counters for 46 // the current process. OnMemoryDump(const MemoryDumpArgs &,ProcessMemoryDump * pmd)47bool ProcessMemoryTotalsDumpProvider::OnMemoryDump( 48 const MemoryDumpArgs& /* args */, 49 ProcessMemoryDump* pmd) { 50 const uint64_t rss_bytes = rss_bytes_for_testing 51 ? rss_bytes_for_testing 52 : process_metrics_->GetWorkingSetSize(); 53 54 uint64_t peak_rss_bytes = 0; 55 56 #if !defined(OS_IOS) 57 peak_rss_bytes = process_metrics_->GetPeakWorkingSetSize(); 58 #if defined(OS_LINUX) || defined(OS_ANDROID) 59 if (kernel_supports_rss_peak_reset) { 60 // TODO(ssid): Fix crbug.com/461788 to write to the file from sandboxed 61 // processes. 62 int clear_refs_fd = open("/proc/self/clear_refs", O_WRONLY); 63 if (clear_refs_fd > 0 && 64 WriteFileDescriptor(clear_refs_fd, kClearPeakRssCommand, 65 sizeof(kClearPeakRssCommand))) { 66 pmd->process_totals()->set_is_peak_rss_resetable(true); 67 } else { 68 kernel_supports_rss_peak_reset = false; 69 } 70 close(clear_refs_fd); 71 } 72 #elif defined(OS_MACOSX) 73 size_t private_bytes; 74 bool res = process_metrics_->GetMemoryBytes(&private_bytes, 75 nullptr /* shared_bytes */); 76 if (res) { 77 pmd->process_totals()->SetExtraFieldInBytes("private_bytes", private_bytes); 78 } 79 #endif // defined(OS_LINUX) || defined(OS_ANDROID) 80 #endif // !defined(OS_IOS) 81 82 if (rss_bytes > 0) { 83 pmd->process_totals()->set_resident_set_bytes(rss_bytes); 84 pmd->process_totals()->set_peak_resident_set_bytes(peak_rss_bytes); 85 pmd->set_has_process_totals(); 86 return true; 87 } 88 89 return false; 90 } 91 92 } // namespace trace_event 93 } // namespace base 94