|  | //===-- MemoryGauge.cpp -----------------------------------------*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "MemoryGauge.h" | 
|  | #include "lldb/lldb-forward.h" | 
|  | #include <assert.h> | 
|  | #include <cmath> | 
|  | #include <mach/mach.h> | 
|  | #include <mach/mach_traps.h> | 
|  | #include <mach/task.h> | 
|  |  | 
|  | using namespace lldb_perf; | 
|  |  | 
|  | MemoryStats::MemoryStats(mach_vm_size_t virtual_size, | 
|  | mach_vm_size_t resident_size, | 
|  | mach_vm_size_t max_resident_size) | 
|  | : m_virtual_size(virtual_size), m_resident_size(resident_size), | 
|  | m_max_resident_size(max_resident_size) {} | 
|  |  | 
|  | MemoryStats::MemoryStats(const MemoryStats &rhs) | 
|  | : m_virtual_size(rhs.m_virtual_size), m_resident_size(rhs.m_resident_size), | 
|  | m_max_resident_size(rhs.m_max_resident_size) {} | 
|  |  | 
|  | MemoryStats &MemoryStats::operator=(const MemoryStats &rhs) { | 
|  | if (this != &rhs) { | 
|  | m_virtual_size = rhs.m_virtual_size; | 
|  | m_resident_size = rhs.m_resident_size; | 
|  | m_max_resident_size = rhs.m_max_resident_size; | 
|  | } | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | MemoryStats &MemoryStats::operator+=(const MemoryStats &rhs) { | 
|  | m_virtual_size += rhs.m_virtual_size; | 
|  | m_resident_size += rhs.m_resident_size; | 
|  | m_max_resident_size += rhs.m_max_resident_size; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | MemoryStats MemoryStats::operator-(const MemoryStats &rhs) { | 
|  | return MemoryStats(m_virtual_size - rhs.m_virtual_size, | 
|  | m_resident_size - rhs.m_resident_size, | 
|  | m_max_resident_size - rhs.m_max_resident_size); | 
|  | } | 
|  |  | 
|  | MemoryStats MemoryStats::operator+(const MemoryStats &rhs) { | 
|  | return MemoryStats(m_virtual_size + rhs.m_virtual_size, | 
|  | m_resident_size + rhs.m_resident_size, | 
|  | m_max_resident_size + rhs.m_max_resident_size); | 
|  | } | 
|  |  | 
|  | MemoryStats MemoryStats::operator/(size_t n) { | 
|  | MemoryStats result(*this); | 
|  | result.m_virtual_size /= n; | 
|  | result.m_resident_size /= n; | 
|  | result.m_max_resident_size /= n; | 
|  | return result; | 
|  | } | 
|  |  | 
|  | MemoryStats MemoryStats::operator*(const MemoryStats &rhs) { | 
|  | return MemoryStats(m_virtual_size * rhs.m_virtual_size, | 
|  | m_resident_size * rhs.m_resident_size, | 
|  | m_max_resident_size * rhs.m_max_resident_size); | 
|  | } | 
|  |  | 
|  | Results::ResultSP MemoryStats::GetResult(const char *name, | 
|  | const char *description) const { | 
|  | std::unique_ptr<Results::Dictionary> dict_ap( | 
|  | new Results::Dictionary(name, NULL)); | 
|  | dict_ap->AddUnsigned("resident", NULL, GetResidentSize()); | 
|  | dict_ap->AddUnsigned("max_resident", NULL, GetMaxResidentSize()); | 
|  | return Results::ResultSP(dict_ap.release()); | 
|  | } | 
|  |  | 
|  | MemoryGauge::ValueType MemoryGauge::Now() { | 
|  | task_t task = mach_task_self(); | 
|  | mach_task_basic_info_data_t taskBasicInfo; | 
|  | mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT; | 
|  | auto task_info_ret = task_info(task, MACH_TASK_BASIC_INFO, | 
|  | (task_info_t)&taskBasicInfo, &count); | 
|  | if (task_info_ret == KERN_SUCCESS) { | 
|  | return MemoryStats(taskBasicInfo.virtual_size, taskBasicInfo.resident_size, | 
|  | taskBasicInfo.resident_size_max); | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | MemoryGauge::MemoryGauge() | 
|  | : m_state(MemoryGauge::State::eNeverUsed), m_start(), m_delta() {} | 
|  |  | 
|  | void MemoryGauge::Start() { | 
|  | m_state = MemoryGauge::State::eCounting; | 
|  | m_start = Now(); | 
|  | } | 
|  |  | 
|  | MemoryGauge::ValueType MemoryGauge::Stop() { | 
|  | m_stop = Now(); | 
|  | assert(m_state == MemoryGauge::State::eCounting && | 
|  | "cannot stop a non-started gauge"); | 
|  | m_state = MemoryGauge::State::eStopped; | 
|  | m_delta = m_stop - m_start; | 
|  | return m_delta; | 
|  | } | 
|  |  | 
|  | MemoryGauge::ValueType MemoryGauge::GetDeltaValue() const { | 
|  | assert(m_state == MemoryGauge::State::eStopped && | 
|  | "gauge must be used before you can evaluate it"); | 
|  | return m_delta; | 
|  | } | 
|  |  | 
|  | template <> | 
|  | Results::ResultSP lldb_perf::GetResult(const char *description, | 
|  | MemoryStats value) { | 
|  | return value.GetResult(NULL, description); | 
|  | } | 
|  |  | 
|  | MemoryStats sqrt(const MemoryStats &arg) { | 
|  | long double virt_size = arg.GetVirtualSize(); | 
|  | long double resident_size = arg.GetResidentSize(); | 
|  | long double max_resident_size = arg.GetMaxResidentSize(); | 
|  |  | 
|  | virt_size = sqrtl(virt_size); | 
|  | resident_size = sqrtl(resident_size); | 
|  | max_resident_size = sqrtl(max_resident_size); | 
|  |  | 
|  | return MemoryStats(virt_size, resident_size, max_resident_size); | 
|  | } |