forked from OSchip/llvm-project
<rdar://problem/13338758>
Make it configurable what to profile. For Mac, we don't use the dirty page size yet and hence there is no need to gather that. This should be way better in not draining the battery since we are operating between 0% to 0.1% on the Mac after this change. llvm-svn: 176451
This commit is contained in:
parent
2a513e8218
commit
8764fe7d9a
|
@ -1220,22 +1220,22 @@ DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *r
|
|||
}
|
||||
|
||||
std::string
|
||||
DNBProcessGetProfileData (nub_process_t pid)
|
||||
DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType)
|
||||
{
|
||||
MachProcessSP procSP;
|
||||
if (GetProcessSP (pid, procSP))
|
||||
return procSP->Task().GetProfileData();
|
||||
return procSP->Task().GetProfileData(scanType);
|
||||
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
nub_bool_t
|
||||
DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec)
|
||||
DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type)
|
||||
{
|
||||
MachProcessSP procSP;
|
||||
if (GetProcessSP (pid, procSP))
|
||||
{
|
||||
procSP->SetEnableAsyncProfiling(enable, interval_usec);
|
||||
procSP->SetEnableAsyncProfiling(enable, interval_usec, scan_type);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,8 +63,8 @@ nub_size_t DNBProcessMemoryWrite (nub_process_t pid, nub_addr_t addr, nub
|
|||
nub_addr_t DNBProcessMemoryAllocate (nub_process_t pid, nub_size_t size, uint32_t permissions) DNB_EXPORT;
|
||||
nub_bool_t DNBProcessMemoryDeallocate (nub_process_t pid, nub_addr_t addr) DNB_EXPORT;
|
||||
int DNBProcessMemoryRegionInfo (nub_process_t pid, nub_addr_t addr, DNBRegionInfo *region_info) DNB_EXPORT;
|
||||
std::string DNBProcessGetProfileData (nub_process_t pid) DNB_EXPORT;
|
||||
nub_bool_t DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec) DNB_EXPORT;
|
||||
std::string DNBProcessGetProfileData (nub_process_t pid, DNBProfileDataScanType scanType) DNB_EXPORT;
|
||||
nub_bool_t DNBProcessSetEnableAsyncProfiling (nub_process_t pid, nub_bool_t enable, uint64_t interval_usec, DNBProfileDataScanType scan_type) DNB_EXPORT;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Process status
|
||||
|
|
|
@ -358,6 +358,23 @@ struct DNBRegionInfo
|
|||
uint32_t permissions;
|
||||
};
|
||||
|
||||
enum DNBProfileDataScanType
|
||||
{
|
||||
eProfileHostCPU = (1 << 0),
|
||||
eProfileCPU = (1 << 1),
|
||||
|
||||
eProfileThreadsCPU = (1 << 2), // By default excludes eProfileThreadName and eProfileQueueName.
|
||||
eProfileThreadName = (1 << 3), // Assume eProfileThreadsCPU, get thread name as well.
|
||||
eProfileQueueName = (1 << 4), // Assume eProfileThreadsCPU, get queue name as well.
|
||||
|
||||
eProfileHostMemory = (1 << 5),
|
||||
|
||||
eProfileMemory = (1 << 6), // By default, excludes eProfileMemoryDirtyPage.
|
||||
eProfileMemoryDirtyPage = (1 << 7), // Assume eProfileMemory, get Dirty Page size as well.
|
||||
|
||||
eProfileAll = 0xffffffff
|
||||
};
|
||||
|
||||
typedef nub_bool_t (*DNBCallbackBreakpointHit)(nub_process_t pid, nub_thread_t tid, nub_break_t breakID, void *baton);
|
||||
typedef nub_addr_t (*DNBCallbackNameToAddress)(nub_process_t pid, const char *name, const char *shlib_regex, void *baton);
|
||||
typedef nub_size_t (*DNBCallbackCopyExecutableImageInfos)(nub_process_t pid, struct DNBExecutableImageInfo **image_infos, nub_bool_t only_changed, void *baton);
|
||||
|
|
|
@ -315,10 +315,11 @@ MachProcess::StartSTDIOThread()
|
|||
}
|
||||
|
||||
void
|
||||
MachProcess::SetEnableAsyncProfiling(bool enable, uint64_t interval_usec)
|
||||
MachProcess::SetEnableAsyncProfiling(bool enable, uint64_t interval_usec, DNBProfileDataScanType scan_type)
|
||||
{
|
||||
m_profile_enabled = enable;
|
||||
m_profile_interval_usec = interval_usec;
|
||||
m_profile_scan_type = scan_type;
|
||||
|
||||
if (m_profile_enabled && (m_profile_thread == NULL))
|
||||
{
|
||||
|
@ -1411,7 +1412,7 @@ MachProcess::ProfileThread(void *arg)
|
|||
nub_state_t state = proc->GetState();
|
||||
if (state == eStateRunning)
|
||||
{
|
||||
std::string data = proc->Task().GetProfileData();
|
||||
std::string data = proc->Task().GetProfileData(proc->GetProfileScanType());
|
||||
if (!data.empty())
|
||||
{
|
||||
proc->SignalAsyncProfileData(data.c_str());
|
||||
|
|
|
@ -148,7 +148,7 @@ public:
|
|||
//----------------------------------------------------------------------
|
||||
// Profile functions
|
||||
//----------------------------------------------------------------------
|
||||
void SetEnableAsyncProfiling (bool enable, uint64_t internal_usec);
|
||||
void SetEnableAsyncProfiling (bool enable, uint64_t internal_usec, DNBProfileDataScanType scan_type);
|
||||
bool IsProfilingEnabled () { return m_profile_enabled; }
|
||||
uint64_t ProfileInterval () { return m_profile_interval_usec; }
|
||||
bool StartProfileThread ();
|
||||
|
@ -250,6 +250,9 @@ public:
|
|||
}
|
||||
|
||||
bool ProcessUsingSpringBoard() const { return (m_flags & eMachProcessFlagsUsingSBS) != 0; }
|
||||
|
||||
DNBProfileDataScanType GetProfileScanType () { return m_profile_scan_type; }
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
|
@ -282,6 +285,7 @@ private:
|
|||
|
||||
bool m_profile_enabled; // A flag to indicate if profiling is enabled
|
||||
uint64_t m_profile_interval_usec; // If enable, the profiling interval in microseconds
|
||||
DNBProfileDataScanType m_profile_scan_type; // Indicates what needs to be profiled
|
||||
pthread_t m_profile_thread; // Thread ID for the thread that profiles the inferior
|
||||
PThreadMutex m_profile_data_mutex; // Multithreaded protection for profile info data
|
||||
std::vector<std::string> m_profile_data; // Profile data, must be protected by m_profile_data_mutex
|
||||
|
|
|
@ -233,7 +233,7 @@ MachTask::GetMemoryRegionInfo (nub_addr_t addr, DNBRegionInfo *region_info)
|
|||
} while (0)
|
||||
|
||||
// We should consider moving this into each MacThread.
|
||||
static void get_threads_profile_data(task_t task, nub_process_t pid, std::vector<uint64_t> &threads_id, std::vector<std::string> &threads_name, std::vector<uint64_t> &threads_used_usec)
|
||||
static void get_threads_profile_data(DNBProfileDataScanType scanType, task_t task, nub_process_t pid, std::vector<uint64_t> &threads_id, std::vector<std::string> &threads_name, std::vector<uint64_t> &threads_used_usec)
|
||||
{
|
||||
kern_return_t kr;
|
||||
thread_act_array_t threads;
|
||||
|
@ -243,7 +243,8 @@ static void get_threads_profile_data(task_t task, nub_process_t pid, std::vector
|
|||
if (kr != KERN_SUCCESS)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < tcnt; i++) {
|
||||
for (int i = 0; i < tcnt; i++)
|
||||
{
|
||||
thread_identifier_info_data_t identifier_info;
|
||||
mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
|
||||
kr = ::thread_info(threads[i], THREAD_IDENTIFIER_INFO, (thread_info_t)&identifier_info, &count);
|
||||
|
@ -254,22 +255,26 @@ static void get_threads_profile_data(task_t task, nub_process_t pid, std::vector
|
|||
kr = ::thread_info(threads[i], THREAD_BASIC_INFO, (thread_info_t)&basic_info, &count);
|
||||
if (kr != KERN_SUCCESS) continue;
|
||||
|
||||
if ((basic_info.flags & TH_FLAGS_IDLE) == 0) {
|
||||
if ((basic_info.flags & TH_FLAGS_IDLE) == 0)
|
||||
{
|
||||
nub_thread_t tid = MachThread::GetGloballyUniqueThreadIDForMachPortID (threads[i]);
|
||||
|
||||
threads_id.push_back(tid);
|
||||
|
||||
if (identifier_info.thread_handle != 0) {
|
||||
if ((scanType & eProfileThreadName) && (identifier_info.thread_handle != 0))
|
||||
{
|
||||
struct proc_threadinfo proc_threadinfo;
|
||||
int len = ::proc_pidinfo(pid, PROC_PIDTHREADINFO, identifier_info.thread_handle, &proc_threadinfo, PROC_PIDTHREADINFO_SIZE);
|
||||
if (len && proc_threadinfo.pth_name[0]) {
|
||||
if (len && proc_threadinfo.pth_name[0])
|
||||
{
|
||||
threads_name.push_back(proc_threadinfo.pth_name);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
threads_name.push_back("");
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
threads_name.push_back("");
|
||||
}
|
||||
struct timeval tv;
|
||||
|
@ -289,26 +294,29 @@ static void get_threads_profile_data(task_t task, nub_process_t pid, std::vector
|
|||
#define RAW_HEXBASE std::setfill('0') << std::hex << std::right
|
||||
#define DECIMAL std::dec << std::setfill(' ')
|
||||
std::string
|
||||
MachTask::GetProfileData ()
|
||||
MachTask::GetProfileData (DNBProfileDataScanType scanType)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
static int32_t numCPU = -1;
|
||||
int32_t mib[] = {CTL_HW, HW_AVAILCPU};
|
||||
size_t len = sizeof(numCPU);
|
||||
if (numCPU == -1)
|
||||
struct host_cpu_load_info host_info;
|
||||
if (scanType & eProfileHostCPU)
|
||||
{
|
||||
if (sysctl(mib, sizeof(mib) / sizeof(int32_t), &numCPU, &len, NULL, 0) != 0)
|
||||
int32_t mib[] = {CTL_HW, HW_AVAILCPU};
|
||||
size_t len = sizeof(numCPU);
|
||||
if (numCPU == -1)
|
||||
{
|
||||
if (sysctl(mib, sizeof(mib) / sizeof(int32_t), &numCPU, &len, NULL, 0) != 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
mach_port_t localHost = mach_host_self();
|
||||
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
|
||||
kern_return_t kr = host_statistics(localHost, HOST_CPU_LOAD_INFO, (host_info_t)&host_info, &count);
|
||||
if (kr != KERN_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
|
||||
mach_port_t localHost = mach_host_self();
|
||||
struct host_cpu_load_info host_info;
|
||||
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
|
||||
kern_return_t kr = host_statistics(localHost, HOST_CPU_LOAD_INFO, (host_info_t)&host_info, &count);
|
||||
if (kr != KERN_SUCCESS)
|
||||
return result;
|
||||
|
||||
task_t task = TaskPort();
|
||||
if (task == TASK_NULL)
|
||||
return result;
|
||||
|
@ -322,24 +330,31 @@ MachTask::GetProfileData ()
|
|||
|
||||
uint64_t elapsed_usec = 0;
|
||||
uint64_t task_used_usec = 0;
|
||||
if (scanType & eProfileCPU)
|
||||
{
|
||||
// Get current used time.
|
||||
struct timeval current_used_time;
|
||||
struct timeval tv;
|
||||
TIME_VALUE_TO_TIMEVAL(&task_info.user_time, ¤t_used_time);
|
||||
TIME_VALUE_TO_TIMEVAL(&task_info.system_time, &tv);
|
||||
timeradd(¤t_used_time, &tv, ¤t_used_time);
|
||||
task_used_usec = current_used_time.tv_sec * 1000000ULL + current_used_time.tv_usec;
|
||||
|
||||
struct timeval current_elapsed_time;
|
||||
int res = gettimeofday(¤t_elapsed_time, NULL);
|
||||
if (res == 0)
|
||||
{
|
||||
elapsed_usec = current_elapsed_time.tv_sec * 1000000ULL + current_elapsed_time.tv_usec;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint64_t> threads_id;
|
||||
std::vector<std::string> threads_name;
|
||||
std::vector<uint64_t> threads_used_usec;
|
||||
|
||||
// Get current used time.
|
||||
struct timeval current_used_time;
|
||||
struct timeval tv;
|
||||
TIME_VALUE_TO_TIMEVAL(&task_info.user_time, ¤t_used_time);
|
||||
TIME_VALUE_TO_TIMEVAL(&task_info.system_time, &tv);
|
||||
timeradd(¤t_used_time, &tv, ¤t_used_time);
|
||||
task_used_usec = current_used_time.tv_sec * 1000000ULL + current_used_time.tv_usec;
|
||||
get_threads_profile_data(task, m_process->ProcessID(), threads_id, threads_name, threads_used_usec);
|
||||
|
||||
struct timeval current_elapsed_time;
|
||||
int res = gettimeofday(¤t_elapsed_time, NULL);
|
||||
if (res == 0)
|
||||
|
||||
if (scanType & eProfileThreadsCPU)
|
||||
{
|
||||
elapsed_usec = current_elapsed_time.tv_sec * 1000000ULL + current_elapsed_time.tv_usec;
|
||||
get_threads_profile_data(scanType, task, m_process->ProcessID(), threads_id, threads_name, threads_used_usec);
|
||||
}
|
||||
|
||||
struct vm_statistics vm_stats;
|
||||
|
@ -349,53 +364,75 @@ MachTask::GetProfileData ()
|
|||
mach_vm_size_t vprvt = 0;
|
||||
mach_vm_size_t vsize = 0;
|
||||
mach_vm_size_t dirty_size = 0;
|
||||
if (m_vm_memory.GetMemoryProfile(task, task_info, m_process->GetCPUType(), m_process->ProcessID(), vm_stats, physical_memory, rprvt, rsize, vprvt, vsize, dirty_size))
|
||||
if (m_vm_memory.GetMemoryProfile(scanType, task, task_info, m_process->GetCPUType(), m_process->ProcessID(), vm_stats, physical_memory, rprvt, rsize, vprvt, vsize, dirty_size))
|
||||
{
|
||||
std::ostringstream profile_data_stream;
|
||||
|
||||
profile_data_stream << "num_cpu:" << numCPU << ';';
|
||||
profile_data_stream << "host_user_ticks:" << host_info.cpu_ticks[CPU_STATE_USER] << ';';
|
||||
profile_data_stream << "host_sys_ticks:" << host_info.cpu_ticks[CPU_STATE_SYSTEM] << ';';
|
||||
profile_data_stream << "host_idle_ticks:" << host_info.cpu_ticks[CPU_STATE_IDLE] << ';';
|
||||
|
||||
profile_data_stream << "elapsed_usec:" << elapsed_usec << ';';
|
||||
profile_data_stream << "task_used_usec:" << task_used_usec << ';';
|
||||
|
||||
int num_threads = threads_id.size();
|
||||
for (int i=0; i<num_threads; i++) {
|
||||
profile_data_stream << "thread_used_id:" << std::hex << threads_id[i] << std::dec << ';';
|
||||
profile_data_stream << "thread_used_usec:" << threads_used_usec[i] << ';';
|
||||
|
||||
profile_data_stream << "thread_used_name:";
|
||||
int len = threads_name[i].size();
|
||||
if (len) {
|
||||
const char *thread_name = threads_name[i].c_str();
|
||||
// Make sure that thread name doesn't interfere with our delimiter.
|
||||
profile_data_stream << RAW_HEXBASE << std::setw(2);
|
||||
const uint8_t *ubuf8 = (const uint8_t *)(thread_name);
|
||||
for (int j=0; j<len; j++)
|
||||
{
|
||||
profile_data_stream << (uint32_t)(ubuf8[j]);
|
||||
}
|
||||
// Reset back to DECIMAL.
|
||||
profile_data_stream << DECIMAL;
|
||||
}
|
||||
profile_data_stream << ';';
|
||||
if (scanType & eProfileHostCPU)
|
||||
{
|
||||
profile_data_stream << "num_cpu:" << numCPU << ';';
|
||||
profile_data_stream << "host_user_ticks:" << host_info.cpu_ticks[CPU_STATE_USER] << ';';
|
||||
profile_data_stream << "host_sys_ticks:" << host_info.cpu_ticks[CPU_STATE_SYSTEM] << ';';
|
||||
profile_data_stream << "host_idle_ticks:" << host_info.cpu_ticks[CPU_STATE_IDLE] << ';';
|
||||
}
|
||||
|
||||
profile_data_stream << "wired:" << vm_stats.wire_count * vm_page_size << ';';
|
||||
profile_data_stream << "active:" << vm_stats.active_count * vm_page_size << ';';
|
||||
profile_data_stream << "inactive:" << vm_stats.inactive_count * vm_page_size << ';';
|
||||
uint64_t total_used_count = vm_stats.wire_count + vm_stats.inactive_count + vm_stats.active_count;
|
||||
profile_data_stream << "used:" << total_used_count * vm_page_size << ';';
|
||||
profile_data_stream << "free:" << vm_stats.free_count * vm_page_size << ';';
|
||||
profile_data_stream << "total:" << physical_memory << ';';
|
||||
if (scanType & eProfileCPU)
|
||||
{
|
||||
profile_data_stream << "elapsed_usec:" << elapsed_usec << ';';
|
||||
profile_data_stream << "task_used_usec:" << task_used_usec << ';';
|
||||
}
|
||||
|
||||
if (scanType & eProfileThreadsCPU)
|
||||
{
|
||||
int num_threads = threads_id.size();
|
||||
for (int i=0; i<num_threads; i++)
|
||||
{
|
||||
profile_data_stream << "thread_used_id:" << std::hex << threads_id[i] << std::dec << ';';
|
||||
profile_data_stream << "thread_used_usec:" << threads_used_usec[i] << ';';
|
||||
|
||||
if (scanType & eProfileThreadName)
|
||||
{
|
||||
profile_data_stream << "thread_used_name:";
|
||||
int len = threads_name[i].size();
|
||||
if (len)
|
||||
{
|
||||
const char *thread_name = threads_name[i].c_str();
|
||||
// Make sure that thread name doesn't interfere with our delimiter.
|
||||
profile_data_stream << RAW_HEXBASE << std::setw(2);
|
||||
const uint8_t *ubuf8 = (const uint8_t *)(thread_name);
|
||||
for (int j=0; j<len; j++)
|
||||
{
|
||||
profile_data_stream << (uint32_t)(ubuf8[j]);
|
||||
}
|
||||
// Reset back to DECIMAL.
|
||||
profile_data_stream << DECIMAL;
|
||||
}
|
||||
profile_data_stream << ';';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (scanType & eProfileHostMemory)
|
||||
profile_data_stream << "total:" << physical_memory << ';';
|
||||
|
||||
if (scanType & eProfileMemory)
|
||||
{
|
||||
profile_data_stream << "wired:" << vm_stats.wire_count * vm_page_size << ';';
|
||||
profile_data_stream << "active:" << vm_stats.active_count * vm_page_size << ';';
|
||||
profile_data_stream << "inactive:" << vm_stats.inactive_count * vm_page_size << ';';
|
||||
uint64_t total_used_count = vm_stats.wire_count + vm_stats.inactive_count + vm_stats.active_count;
|
||||
profile_data_stream << "used:" << total_used_count * vm_page_size << ';';
|
||||
profile_data_stream << "free:" << vm_stats.free_count * vm_page_size << ';';
|
||||
|
||||
profile_data_stream << "rprvt:" << rprvt << ';';
|
||||
profile_data_stream << "rsize:" << rsize << ';';
|
||||
profile_data_stream << "vprvt:" << vprvt << ';';
|
||||
profile_data_stream << "vsize:" << vsize << ';';
|
||||
|
||||
if (scanType & eProfileMemoryDirtyPage)
|
||||
profile_data_stream << "dirty:" << dirty_size << ';';
|
||||
}
|
||||
|
||||
profile_data_stream << "rprvt:" << rprvt << ';';
|
||||
profile_data_stream << "rsize:" << rsize << ';';
|
||||
profile_data_stream << "vprvt:" << vprvt << ';';
|
||||
profile_data_stream << "vsize:" << vsize << ';';
|
||||
profile_data_stream << "dirty:" << dirty_size << ';';
|
||||
profile_data_stream << "--end--;";
|
||||
|
||||
result = profile_data_stream.str();
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <string>
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "DNBDefs.h"
|
||||
#include "MachException.h"
|
||||
#include "MachVMMemory.h"
|
||||
#include "PThreadMutex.h"
|
||||
|
@ -66,7 +67,7 @@ public:
|
|||
nub_size_t ReadMemory (nub_addr_t addr, nub_size_t size, void *buf);
|
||||
nub_size_t WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf);
|
||||
int GetMemoryRegionInfo (nub_addr_t addr, DNBRegionInfo *region_info);
|
||||
std::string GetProfileData ();
|
||||
std::string GetProfileData (DNBProfileDataScanType scanType);
|
||||
|
||||
nub_addr_t AllocateMemory (nub_size_t size, uint32_t permissions);
|
||||
nub_bool_t DeallocateMemory (nub_addr_t addr);
|
||||
|
|
|
@ -397,21 +397,29 @@ static void GetMemorySizes(task_t task, cpu_type_t cputype, nub_process_t pid, m
|
|||
}
|
||||
|
||||
nub_bool_t
|
||||
MachVMMemory::GetMemoryProfile(task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics_data_t &vm_stats, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size)
|
||||
MachVMMemory::GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics_data_t &vm_stats, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size)
|
||||
{
|
||||
static mach_port_t localHost = mach_host_self();
|
||||
mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
|
||||
host_statistics(localHost, HOST_VM_INFO, (host_info_t)&vm_stats, &count);
|
||||
vm_stats.wire_count += GetStolenPages();
|
||||
physical_memory = GetPhysicalMemory();
|
||||
|
||||
// This uses vmmap strategy. We don't use the returned rsize for now. We prefer to match top's version since that's what we do for the rest of the metrics.
|
||||
GetRegionSizes(task, rsize, dirty_size);
|
||||
if (scanType & eProfileHostMemory)
|
||||
physical_memory = GetPhysicalMemory();
|
||||
|
||||
GetMemorySizes(task, cputype, pid, rprvt, vprvt);
|
||||
if (scanType & eProfileMemory)
|
||||
{
|
||||
static mach_port_t localHost = mach_host_self();
|
||||
mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
|
||||
host_statistics(localHost, HOST_VM_INFO, (host_info_t)&vm_stats, &count);
|
||||
vm_stats.wire_count += GetStolenPages();
|
||||
|
||||
rsize = ti.resident_size;
|
||||
vsize = ti.virtual_size;
|
||||
GetMemorySizes(task, cputype, pid, rprvt, vprvt);
|
||||
|
||||
rsize = ti.resident_size;
|
||||
vsize = ti.virtual_size;
|
||||
}
|
||||
|
||||
if (scanType & eProfileMemoryDirtyPage)
|
||||
{
|
||||
// This uses vmmap strategy. We don't use the returned rsize for now. We prefer to match top's version since that's what we do for the rest of the metrics.
|
||||
GetRegionSizes(task, rsize, dirty_size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
nub_size_t Write(task_t task, nub_addr_t address, const void *data, nub_size_t data_count);
|
||||
nub_size_t PageSize();
|
||||
nub_bool_t GetMemoryRegionInfo(task_t task, nub_addr_t address, DNBRegionInfo *region_info);
|
||||
nub_bool_t GetMemoryProfile(task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics_data_t &vm_stats, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size);
|
||||
nub_bool_t GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics_data_t &vm_stats, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size);
|
||||
|
||||
protected:
|
||||
nub_size_t MaxBytesLeftInPage(nub_addr_t addr, nub_size_t count);
|
||||
|
|
|
@ -3645,14 +3645,32 @@ RNBRemote::HandlePacket_MemoryRegionInfo (const char *p)
|
|||
return SendPacket (ostrm.str());
|
||||
}
|
||||
|
||||
// qGetProfileData;scan_type:0xYYYYYYY
|
||||
rnb_err_t
|
||||
RNBRemote::HandlePacket_GetProfileData (const char *p)
|
||||
{
|
||||
nub_process_t pid = m_ctx.ProcessID();
|
||||
if (pid == INVALID_NUB_PROCESS)
|
||||
return SendPacket ("OK");
|
||||
|
||||
std::string data = DNBProcessGetProfileData(pid);
|
||||
|
||||
StringExtractor packet(p += sizeof ("qGetProfileData"));
|
||||
DNBProfileDataScanType scan_type = eProfileAll;
|
||||
std::string name;
|
||||
std::string value;
|
||||
while (packet.GetNameColonValue(name, value))
|
||||
{
|
||||
if (name.compare ("scan_type") == 0)
|
||||
{
|
||||
std::istringstream iss(value);
|
||||
uint32_t int_value = 0;
|
||||
if (iss >> std::hex >> int_value)
|
||||
{
|
||||
scan_type = (DNBProfileDataScanType)int_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string data = DNBProcessGetProfileData(pid, scan_type);
|
||||
if (!data.empty())
|
||||
{
|
||||
return SendPacket (data.c_str());
|
||||
|
@ -3663,18 +3681,18 @@ RNBRemote::HandlePacket_GetProfileData (const char *p)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;
|
||||
// QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY
|
||||
rnb_err_t
|
||||
RNBRemote::HandlePacket_SetEnableAsyncProfiling (const char *p)
|
||||
{
|
||||
nub_process_t pid = m_ctx.ProcessID();
|
||||
if (pid == INVALID_NUB_PROCESS)
|
||||
return SendPacket ("");
|
||||
return SendPacket ("OK");
|
||||
|
||||
StringExtractor packet(p += sizeof ("QSetEnableAsyncProfiling:") - 1);
|
||||
StringExtractor packet(p += sizeof ("QSetEnableAsyncProfiling"));
|
||||
bool enable = false;
|
||||
uint64_t interval_usec = 0;
|
||||
DNBProfileDataScanType scan_type = eProfileAll;
|
||||
std::string name;
|
||||
std::string value;
|
||||
while (packet.GetNameColonValue(name, value))
|
||||
|
@ -3687,13 +3705,23 @@ RNBRemote::HandlePacket_SetEnableAsyncProfiling (const char *p)
|
|||
{
|
||||
interval_usec = strtoul(value.c_str(), NULL, 10);
|
||||
}
|
||||
else if (name.compare ("scan_type") == 0)
|
||||
{
|
||||
std::istringstream iss(value);
|
||||
uint32_t int_value = 0;
|
||||
if (iss >> std::hex >> int_value)
|
||||
{
|
||||
scan_type = (DNBProfileDataScanType)int_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (interval_usec == 0)
|
||||
{
|
||||
enable = 0;
|
||||
}
|
||||
DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec);
|
||||
|
||||
DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type);
|
||||
return SendPacket ("OK");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue