Objective c 如何测量iOS线程的实际CPU时间?
我正在寻找用于Android、Microsoft或Posix的iOS模拟程序和函数,以测量多线程应用程序中函数使用的实际“清除”时间。也就是说,我不想测量函数中实际的挂钟时间,而是CPU时间 我发现关于这一点的讨论很有趣。不幸的是,两者都不适用于iOSObjective c 如何测量iOS线程的实际CPU时间?,objective-c,ios,multithreading,profiling,pthreads,Objective C,Ios,Multithreading,Profiling,Pthreads,我正在寻找用于Android、Microsoft或Posix的iOS模拟程序和函数,以测量多线程应用程序中函数使用的实际“清除”时间。也就是说,我不想测量函数中实际的挂钟时间,而是CPU时间 我发现关于这一点的讨论很有趣。不幸的是,两者都不适用于iOS iOS上有类似的函数吗?从它的描述来看,clock()函数似乎满足了您的需要 如果有人在寻找一个好答案: 不久前,我在中发现了一些很棒的代码(用于在OSX中查找CPU时间/内存使用情况),并对其进行了一些修改。我用它来测试ARM上的一些NEON优
iOS上有类似的函数吗?从它的描述来看,clock()函数似乎满足了您的需要
如果有人在寻找一个好答案: 不久前,我在中发现了一些很棒的代码(用于在OSX中查找CPU时间/内存使用情况),并对其进行了一些修改。我用它来测试ARM上的一些NEON优化。您可能只需要获取当前线程时间的部分
#include <sys/types.h>
#include <sys/sysctl.h>
#include <mach/mach_init.h>
#include <mach/mach_host.h>
#include <mach/mach_port.h>
#include <mach/mach_traps.h>
#include <mach/task_info.h>
#include <mach/thread_info.h>
#include <mach/thread_act.h>
#include <mach/vm_region.h>
#include <mach/vm_map.h>
#include <mach/task.h>
typedef struct {
double utime, stime;
} CPUTime;
int get_cpu_time(CPUTime *rpd, bool_t thread_only)
{
task_t task;
kern_return_t error;
mach_msg_type_number_t count;
thread_array_t thread_table;
thread_basic_info_t thi;
thread_basic_info_data_t thi_data;
unsigned table_size;
struct task_basic_info ti;
if (thread_only) {
// just get time of this thread
count = THREAD_BASIC_INFO_COUNT;
thi = &thi_data;
error = thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
rpd->utime = thi->user_time.seconds + thi->user_time.microseconds * 1e-6;
rpd->stime = thi->system_time.seconds + thi->system_time.microseconds * 1e-6;
return 0;
}
// get total time of the current process
task = mach_task_self();
count = TASK_BASIC_INFO_COUNT;
error = task_info(task, TASK_BASIC_INFO, (task_info_t)&ti, &count);
assert(error == KERN_SUCCESS);
{ /* calculate CPU times, adapted from top/libtop.c */
unsigned i;
// the following times are for threads which have already terminated and gone away
rpd->utime = ti.user_time.seconds + ti.user_time.microseconds * 1e-6;
rpd->stime = ti.system_time.seconds + ti.system_time.microseconds * 1e-6;
error = task_threads(task, &thread_table, &table_size);
assert(error == KERN_SUCCESS);
thi = &thi_data;
// for each active thread, add up thread time
for (i = 0; i != table_size; ++i) {
count = THREAD_BASIC_INFO_COUNT;
error = thread_info(thread_table[i], THREAD_BASIC_INFO, (thread_info_t)thi, &count);
assert(error == KERN_SUCCESS);
if ((thi->flags & TH_FLAGS_IDLE) == 0) {
rpd->utime += thi->user_time.seconds + thi->user_time.microseconds * 1e-6;
rpd->stime += thi->system_time.seconds + thi->system_time.microseconds * 1e-6;
}
error = mach_port_deallocate(mach_task_self(), thread_table[i]);
assert(error == KERN_SUCCESS);
}
error = vm_deallocate(mach_task_self(), (vm_offset_t)thread_table, table_size * sizeof(thread_array_t));
assert(error == KERN_SUCCESS);
}
if (task != mach_task_self()) {
mach_port_deallocate(mach_task_self(), task);
assert(error == KERN_SUCCESS);
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
类型定义结构{
双倍使用时间;
}CPUTime;
int get_cpu_时间(仅限CPUTime*rpd、bool_t线程)
{
任务任务;
内核返回错误;
马赫数、信号类型、数量、计数;
线程数组线程表;
线程基本信息;
线程\u基本信息\u数据\u该数据;
无符号表格大小;
结构任务\基本\信息ti;
如果(仅螺纹){
//只需获取此线程的时间
计数=线程\基本\信息\计数;
thi=&thi_数据;
错误=线程信息(马赫线程自身()、线程基本信息、(线程信息)thi和计数);
rpd->utime=thi->user\u time.seconds+thi->user\u time.microseconds*1e-6;
rpd->stime=thi->system_time.seconds+thi->system_time.microsonds*1e-6;
返回0;
}
//获取当前进程的总时间
task=mach_task_self();
计数=任务\基本\信息\计数;
错误=任务信息(任务、任务基本信息、(任务信息)&ti和计数);
断言(error==KERN_SUCCESS);
{/*计算CPU时间,根据top/libtop.c改编*/
未签名的i;
//以下时间适用于已经终止并离开的线程
rpd->utime=ti.user\u time.seconds+ti.user\u time.microsonds*1e-6;
rpd->stime=ti.system\u time.seconds+ti.system\u time.microsonds*1e-6;
错误=任务线程(任务、线程表和表大小);
断言(error==KERN_SUCCESS);
thi=&thi_数据;
//对于每个活动线程,添加线程时间
对于(i=0;i!=表格大小;++i){
计数=线程\基本\信息\计数;
错误=线程信息(线程表[i]、线程基本信息、(线程信息)thi和计数);
断言(error==KERN_SUCCESS);
如果((thi->flags&TH_flags_IDLE)==0){
rpd->utime+=thi->user\u time.seconds+thi->user\u time.microseconds*1e-6;
rpd->stime+=thi->system_time.seconds+thi->system_time.microsonds*1e-6;
}
错误=mach_port_deallocate(mach_task_self(),thread_table[i]);
断言(error==KERN_SUCCESS);
}
错误=vm_释放(mach_task_self(),(vm_offset_t)thread_table,table_size*sizeof(thread_array_t));
断言(error==KERN_SUCCESS);
}
if(task!=mach_task_self()){
mach_port_deallocate(mach_task_self(),task);
断言(error==KERN_SUCCESS);
}
返回0;
}
我使用此代码测量线程CPU时间。它基于,但更加简洁和集中
线程时间
\ifndef线程时间\u h
#定义线程时间
#包括
typedef结构线程时间{
int64用户时间;
int64系统时间;
}线程时间;
线程时间线程时间();
线程时间线程时间子线程(线程时间常数a、线程时间常数b);
#endif/*线程时间*/
线程时间
#包括“thread\u time.h”
#包括
#包括
#包括
int64时间值到时间值(时间值常数){
返回(int64_t)t.秒*1000000+t.微秒;
}
线程时间线程时间(){
线程基本信息数据基本信息;
马赫数、型号、编号、计数=螺纹数、基本信息数;
kern\u return\u t const result=线程信息(mach\u thread\u self(),线程基本信息,(线程信息)&基本信息,&计数);
如果(结果==KERN_SUCCESS){
返回(线程时间){
.user\u time\u us=时间值\u到\u us(基本信息.user\u时间),
.system\u time\u us=时间\u值\u到\u us(基本信息.system\u时间)
};
}否则{
返回(线程时间){-1,-1};
}
}
线程时间线程时间子线程(线程时间常数a、线程时间常数b){
返回(线程时间){
.user\u time\u us=a.user\u time\u us-b.user\u time\u us,
.system\u time\u us=a.system\u time\u us-b.system\u time\u us
};
}
您只是在寻找精确的挂钟时间吗?如果是这样的话,这个问题的答案应该是有效的:@Brad Larson:不,我想测量与挂钟相反的时间,来测量给定线程使用的纯CPU时间。只是想检查一下:你真的需要在代码中加入这个吗?Instruments在不需要修改程序的情况下做得很好。Rob的观点是Instruments具有很强的功能,可以只在CPU上显示方法的执行时间(Shark也是如此,但Instruments更容易使用)。您也可以使用DTrace的vtimestamp
,就像我在本文“时间配置”部分中所展示的那样:,但这只适用于在iOS模拟器中运行的应用程序,而不适用于实际设备。这很酷,但不幸的是,我的配置非常特定于ARM处理器,因此iOS模拟器与此无关。不幸的是,时钟()除了非常不准确外,还不能测量每个线程的时间。是的!这给了我们丢失的信息!!碰巧你有这样的linux/android版本吗?@JoelTeply这段代码使用Mach内核API,所以它是macOS及其衍生产品(iOS、watchOS、tvOS)特有的。不幸的是,我没有针对LinuxK的适应性
#ifndef thread_time_h
#define thread_time_h
#include <stdint.h>
typedef struct thread_time {
int64_t user_time_us;
int64_t system_time_us;
} thread_time_t;
thread_time_t thread_time();
thread_time_t thread_time_sub(thread_time_t const a, thread_time_t const b);
#endif /* thread_time_h */
#include "thread_time.h"
#include <mach/mach_init.h>
#include <mach/thread_act.h>
#include <mach/thread_info.h>
int64_t time_value_to_us(time_value_t const t) {
return (int64_t)t.seconds * 1000000 + t.microseconds;
}
thread_time_t thread_time() {
thread_basic_info_data_t basic_info;
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
kern_return_t const result = thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)&basic_info, &count);
if (result == KERN_SUCCESS) {
return (thread_time_t){
.user_time_us = time_value_to_us(basic_info.user_time),
.system_time_us = time_value_to_us(basic_info.system_time)
};
} else {
return (thread_time_t){-1, -1};
}
}
thread_time_t thread_time_sub(thread_time_t const a, thread_time_t const b) {
return (thread_time_t){
.user_time_us = a.user_time_us - b.user_time_us,
.system_time_us = a.system_time_us - b.system_time_us
};
}