Index: ios/chrome/browser/memory/memory_metrics.cc |
diff --git a/ios/chrome/browser/memory/memory_metrics.cc b/ios/chrome/browser/memory/memory_metrics.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..360c533f396221b3f8b5d072599a09895d2a625a |
--- /dev/null |
+++ b/ios/chrome/browser/memory/memory_metrics.cc |
@@ -0,0 +1,89 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ios/chrome/browser/memory/memory_metrics.h" |
+ |
+#include <mach/mach.h> |
+ |
+#include "base/logging.h" |
+#include "base/process/process_handle.h" |
+#include "base/process/process_metrics.h" |
+ |
+#ifdef ARCH_CPU_64_BITS |
+#define cr_vm_region vm_region_64 |
+#else |
+#define cr_vm_region vm_region |
+#endif |
+ |
+namespace { |
+// The number of pages returned by host_statistics and vm_region are a count |
+// of pages of 4096 bytes even when running on arm64 but the constants that |
+// are exposed (vm_page_size, VM_PAGE_SIZE, host_page_size) are all equals to |
+// 16384 bytes. So we define our own constant here to convert from page count |
+// to bytes. |
+const uint64_t kVMPageSize = 4096; |
+} |
+ |
+namespace memory_util { |
+ |
+uint64 GetFreePhysicalBytes() { |
+ vm_statistics_data_t vmstat; |
+ mach_msg_type_number_t count = HOST_VM_INFO_COUNT; |
+ kern_return_t result = |
+ host_statistics(mach_host_self(), HOST_VM_INFO, |
+ reinterpret_cast<host_info_t>(&vmstat), &count); |
+ if (result != KERN_SUCCESS) { |
+ LOG(ERROR) << "Calling host_statistics failed."; |
+ return 0; |
+ } |
+ return vmstat.free_count * kVMPageSize; |
+} |
+ |
+uint64 GetRealMemoryUsedInBytes() { |
+ base::ProcessHandle process_handle = base::GetCurrentProcessHandle(); |
+ scoped_ptr<base::ProcessMetrics> process_metrics( |
+ base::ProcessMetrics::CreateProcessMetrics(process_handle)); |
+ return static_cast<uint64>(process_metrics->GetWorkingSetSize()); |
+} |
+ |
+uint64 GetDirtyVMBytes() { |
+ // Iterate over all VM regions and sum their dirty pages. |
+ unsigned int total_dirty_pages = 0; |
+ vm_size_t vm_size = 0; |
+ kern_return_t result; |
+ for (vm_address_t address = MACH_VM_MIN_ADDRESS;; address += vm_size) { |
+ vm_region_extended_info_data_t info; |
+ mach_msg_type_number_t info_count = VM_REGION_EXTENDED_INFO_COUNT; |
+ mach_port_t object_name; |
+ result = cr_vm_region( |
+ mach_task_self(), &address, &vm_size, VM_REGION_EXTENDED_INFO, |
+ reinterpret_cast<vm_region_info_t>(&info), &info_count, &object_name); |
+ if (result == KERN_INVALID_ADDRESS) { |
+ // The end of the address space has been reached. |
+ break; |
+ } else if (result != KERN_SUCCESS) { |
+ LOG(ERROR) << "Calling vm_region failed with code: " << result; |
+ break; |
+ } else { |
+ total_dirty_pages += info.pages_dirtied; |
+ } |
+ } |
+ return total_dirty_pages * kVMPageSize; |
+} |
+ |
+uint64 GetInternalVMBytes() { |
+ task_vm_info_data_t task_vm_info; |
+ mach_msg_type_number_t count = TASK_VM_INFO_COUNT; |
+ kern_return_t result = |
+ task_info(mach_task_self(), TASK_VM_INFO, |
+ reinterpret_cast<task_info_t>(&task_vm_info), &count); |
+ if (result != KERN_SUCCESS) { |
+ LOG(ERROR) << "Calling task_info failed."; |
+ return 0; |
+ } |
+ |
+ return static_cast<uint64>(task_vm_info.internal); |
+} |
+ |
+} // namespace memory_util |