1 // Copyright 2014 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.
5 #include "ios/chrome/browser/memory/memory_metrics.h"
9 #include "base/logging.h"
10 #include "base/process/process_handle.h"
11 #include "base/process/process_metrics.h"
13 #ifdef ARCH_CPU_64_BITS
14 #define cr_vm_region vm_region_64
16 #define cr_vm_region vm_region
20 // The number of pages returned by host_statistics and vm_region are a count
21 // of pages of 4096 bytes even when running on arm64 but the constants that
22 // are exposed (vm_page_size, VM_PAGE_SIZE, host_page_size) are all equals to
23 // 16384 bytes. So we define our own constant here to convert from page count
25 const uint64_t kVMPageSize
= 4096;
28 namespace memory_util
{
30 uint64
GetFreePhysicalBytes() {
31 vm_statistics_data_t vmstat
;
32 mach_msg_type_number_t count
= HOST_VM_INFO_COUNT
;
33 kern_return_t result
=
34 host_statistics(mach_host_self(), HOST_VM_INFO
,
35 reinterpret_cast<host_info_t
>(&vmstat
), &count
);
36 if (result
!= KERN_SUCCESS
) {
37 LOG(ERROR
) << "Calling host_statistics failed.";
40 return vmstat
.free_count
* kVMPageSize
;
43 uint64
GetRealMemoryUsedInBytes() {
44 base::ProcessHandle process_handle
= base::GetCurrentProcessHandle();
45 scoped_ptr
<base::ProcessMetrics
> process_metrics(
46 base::ProcessMetrics::CreateProcessMetrics(process_handle
));
47 return static_cast<uint64
>(process_metrics
->GetWorkingSetSize());
50 uint64
GetDirtyVMBytes() {
51 // Iterate over all VM regions and sum their dirty pages.
52 unsigned int total_dirty_pages
= 0;
53 vm_size_t vm_size
= 0;
55 for (vm_address_t address
= MACH_VM_MIN_ADDRESS
;; address
+= vm_size
) {
56 vm_region_extended_info_data_t info
;
57 mach_msg_type_number_t info_count
= VM_REGION_EXTENDED_INFO_COUNT
;
58 mach_port_t object_name
;
59 result
= cr_vm_region(
60 mach_task_self(), &address
, &vm_size
, VM_REGION_EXTENDED_INFO
,
61 reinterpret_cast<vm_region_info_t
>(&info
), &info_count
, &object_name
);
62 if (result
== KERN_INVALID_ADDRESS
) {
63 // The end of the address space has been reached.
65 } else if (result
!= KERN_SUCCESS
) {
66 LOG(ERROR
) << "Calling vm_region failed with code: " << result
;
69 total_dirty_pages
+= info
.pages_dirtied
;
72 return total_dirty_pages
* kVMPageSize
;
75 uint64
GetInternalVMBytes() {
76 task_vm_info_data_t task_vm_info
;
77 mach_msg_type_number_t count
= TASK_VM_INFO_COUNT
;
78 kern_return_t result
=
79 task_info(mach_task_self(), TASK_VM_INFO
,
80 reinterpret_cast<task_info_t
>(&task_vm_info
), &count
);
81 if (result
!= KERN_SUCCESS
) {
82 LOG(ERROR
) << "Calling task_info failed.";
86 return static_cast<uint64
>(task_vm_info
.internal
);
89 } // namespace memory_util