• iOS 获取APP的CPU、内存等信息


    目标是开发一个SDK,嵌入到APP里面,用来统计当前APP的实时CPU、内存等信息

    2015.11.17

    http://stackoverflow.com/questions/12889422/ios-cpu-usage-for-each-process-using-sysctl

    这是第一个找到,采用的是sysctl函数

    但是出来的CPU数据和instrument、GT的数据对不上(后两者数据比较接近)

    2015.11.19

    https://github.com/TianJIANG/ios_monitor

    从guithub上搜到的,利用的主要是#import <mach/mach.h> 里面的task_info 等,打开了一道新的大门,后续找到不少类似的方法

    http://stackoverflow.com/questions/8223348/ios-get-cpu-usage-from-application

    这个答案也是给的这个方法,末尾额外加了一行代码, vm_dealloc,解决leaking问题

    补充几个相关的:

    http://stackoverflow.com/questions/5182924/where-is-my-ipad-runtime-memory-going%E2%80%8C%E2%80%8B

    http://blog.sina.com.cn/s/blog_693de6100101ffwm.html

    http://www.zhihu.com/question/22992491

    Github 搜 “Activity Monitor”

    https://github.com/AndrewBarba/ActivityMonitor

    https://github.com/vsnrain/ActivityMonitor

    此算法是获取当前APP的CPU,数值与Instrument、GT接近

    - (void)GetCpuUsage {
        kern_return_t kr;
        task_info_data_t tinfo;
        mach_msg_type_number_t task_info_count;
        
        task_info_count = TASK_INFO_MAX;
        kr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)tinfo, &task_info_count);
        if (kr != KERN_SUCCESS) {
            return;
        }
        
        task_basic_info_t      basic_info;
        thread_array_t         thread_list;
        mach_msg_type_number_t thread_count;
        
        thread_info_data_t     thinfo;
        mach_msg_type_number_t thread_info_count;
        
        thread_basic_info_t basic_info_th;
        uint32_t stat_thread = 0; // Mach threads
        
        basic_info = (task_basic_info_t)tinfo;
        
        // get threads in the task
        kr = task_threads(mach_task_self(), &thread_list, &thread_count);
        if (kr != KERN_SUCCESS) {
            return;
        }
        if (thread_count > 0)
            stat_thread += thread_count;
        
        long tot_sec = 0;
        long tot_usec = 0;
        float tot_cpu = 0;
        int j;
        
        for (j = 0; j < thread_count; j++)
        {
            thread_info_count = THREAD_INFO_MAX;
            kr = thread_info(thread_list[j], THREAD_BASIC_INFO,
                             (thread_info_t)thinfo, &thread_info_count);
            if (kr != KERN_SUCCESS) {
                return;
            }
            
            basic_info_th = (thread_basic_info_t)thinfo;
            
            if (!(basic_info_th->flags & TH_FLAGS_IDLE)) {
                tot_sec = tot_sec + basic_info_th->user_time.seconds + basic_info_th->system_time.seconds;
                tot_usec = tot_usec + basic_info_th->system_time.microseconds + basic_info_th->system_time.microseconds;
                tot_cpu = tot_cpu + basic_info_th->cpu_usage / (float)TH_USAGE_SCALE * 100.0;
            }
            
        } // for each thread
        
        kr = vm_deallocate(mach_task_self(), (vm_offset_t)thread_list, thread_count * sizeof(thread_t));
        assert(kr == KERN_SUCCESS);
        
        NSLog(@"CPU Usage: %f 
    ", tot_cpu);
    }

    此算法是获取当前APP的内存,数值与GT的一致,与Instrument不一致

    - (void)GetCurrentTaskUsedMemory {
        task_basic_info_data_t taskInfo;
        mach_msg_type_number_t infoCount = TASK_BASIC_INFO_COUNT;
        kern_return_t kernReturn = task_info(mach_task_self(),
                                             TASK_BASIC_INFO, (task_info_t)&taskInfo, &infoCount);
        
        if(kernReturn != KERN_SUCCESS) {
            return;
        }
        
        NSLog(@"Memory Usage: %f", taskInfo.resident_size / 1024.0 / 1024.0);
    }

    2015.11.20

    XNU

    https://en.wikipedia.org/wiki/XNU

    MACH

    https://en.wikipedia.org/wiki/Mach_(kernel)

    Kernel Programming Guide

    https://developer.apple.com/library/mac/documentation/Darwin/Conceptual/KernelProgramming/About/About.html

    github 上搜 mach_msg_type_number_t

    https://github.com/search?l=objective-c&q=mach_msg_type_number_t&type=Code&utf8=✓

    2015.11.22

    用VM Tracker查看内存,有那么几项

    Resident Size|Dirty Size|Virtual Size

    http://stackoverflow.com/questions/5176074/what-do-dirty-and-resident-mean-in-relation-to-virtual-memory

    这篇解释了三者的差别,我理解我们应该跟踪的是Resident Size,但是数值上与VM Tracker上对不上 

    - (void)GetMemoryStatistics {
        
        // Get Page Size
        int mib[2];
        int page_size;
        size_t len;
        
        mib[0] = CTL_HW;
        mib[1] = HW_PAGESIZE;
        len = sizeof(page_size);
        
    //    // 方法一: 16384
    //    int status = sysctl(mib, 2, &page_size, &len, NULL, 0);
    //    if (status < 0) {
    //        perror("Failed to get page size");
    //    }
    //    // 方法二: 16384
    //    page_size = getpagesize();
        // 方法三: 4096
        if( host_page_size(mach_host_self(), &page_size)!= KERN_SUCCESS ){
            perror("Failed to get page size");
        }
        printf("Page size is %d bytes
    ", page_size);
        
        // Get Memory Size
        mib[0] = CTL_HW;
        mib[1] = HW_MEMSIZE;
        long ram;
        len = sizeof(ram);
        if (sysctl(mib, 2, &ram, &len, NULL, 0)) {
            perror("Failed to get ram size");
        }
        printf("Ram size is %f MB
    ", ram / (1024.0) / (1024.0));
        
        // Get Memory Statistics
    //    vm_statistics_data_t vm_stats;
    //    mach_msg_type_number_t info_count = HOST_VM_INFO_COUNT;
        vm_statistics64_data_t vm_stats;
        mach_msg_type_number_t info_count64 = HOST_VM_INFO64_COUNT;
    //    kern_return_t kern_return = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stats, &info_count);
        kern_return_t kern_return = host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t)&vm_stats, &info_count64);
        if (kern_return != KERN_SUCCESS) {
            printf("Failed to get VM statistics!");
        }
        
        double vm_total = vm_stats.wire_count + vm_stats.active_count + vm_stats.inactive_count + vm_stats.free_count;
        double vm_wire = vm_stats.wire_count;
        double vm_active = vm_stats.active_count;
        double vm_inactive = vm_stats.inactive_count;
        double vm_free = vm_stats.free_count;
        double unit = (1024.0) * (1024.0);
        
        NSLog(@"Total Memory: %f", vm_total * page_size / unit);
        NSLog(@"Wired Memory: %f", vm_wire * page_size / unit);
        NSLog(@"Active Memory: %f", vm_active * page_size / unit);
        NSLog(@"Inactive Memory: %f", vm_inactive * page_size / unit);
        NSLog(@"Free Memory: %f", vm_free * page_size / unit);
    }

    1、关于Ram大小,用HW_MEMSIZE计算得到1000MB,是准确的

    2、关于page size,上面提供了三种方法

    其中方法一、二在64位机器上返回了16384,只有第三种方法返回了4096

    http://stackoverflow.com/questions/21552747/strange-behavior-on-64bit-ios-devices-when-retrieving-vm-statistics/33574804#33574804

    这篇文章提出了此疑问,但是没有特别明确的解释

    我认为page size应该是4096,用VM Tracker运行,截图如下:

     

    以第一项_LINKEDIT为例,13692*4096/1024/1024=53.48M,与Vitual Size吻合

    3、关于vm_total、vm_wire、vm_active、vm_inactive、vm_free这几个值

    其中一组运行结果如下:

    Page size is 4096 bytes
    Ram size is 1000.000000 MB
    2015-11-22 20:59:41.191 CompSDKDemo[1602:410503] Total Memory: 777.519531
    2015-11-22 20:59:41.191 CompSDKDemo[1602:410503] Wired Memory: 205.484375
    2015-11-22 20:59:41.192 CompSDKDemo[1602:410503] Active Memory: 374.941406
    2015-11-22 20:59:41.192 CompSDKDemo[1602:410503] Inactive Memory: 175.710938
    2015-11-22 20:59:41.192 CompSDKDemo[1602:410503] Free Memory: 21.382812

    可以看到,Total Memory不是1000MB,这个如何解释呢?

    a. 1000M应该是实际的RAM大小,而Total Memory,应该是Virtual Memory,两者是否一回事,有待商榷?

    b. 从APP Store上下了一个System Monitor,如下:

    可以看到,Wired、Active、Inactive的值都对得上,唯独Free的值对不上

    不负责任的猜测,他的Free是通过1000M减其它三项得到的

    Source Code : Get Hardware Info of iPhone

    http://blog.sina.com.cn/s/blog_4a04a3c90100r9gn.html

    How to determine CPU and memory consumption from inside a process? 

    http://stackoverflow.com/questions/63166/how-to-determine-cpu-and-memory-consumption-from-inside-a-process

    总结下来,关于内存的有两个问题:

    1. active、inactive、wired、free加起来不等于1000M

      这个可以先放一放,我们可以先不用管这部分

    2. 当前app消耗的内存,目前的算法与 Debug Gauges的值有偏差,与GT吻合

      不过发现点击页面增长的值和发回释放的值,与Debug Gauges基本一致,因此可以使用

    关于CPU,上面算法给出的值符合要求,可以使用;

    接下来是:耗电量、网速、帧率

    2015.11.23

    耗电量,目前没有找到合适的工具

    有两种获取电池电量信息的方法

    方法一:

    这个方法需要导入 IOKit 库,但是不知从什么时候开始,iOS系统不允许用户导入库

    http://www.cocoachina.com/bbs/read.php?tid=268692

    这篇文章提供了野路子方法,但是实施起来颇为不便,考虑到要做sdk,不适合

    CFTypeRef blob = IOPSCopyPowerSourcesInfo();
    CFArrayRef sources = IOPSCopyPowerSourcesList(blob);

    方法二:

    [UIDevice currentDevice].batteryLevel

    据说精度达到1%

    找到一篇文章,提供了三种方法

    iOS开发之runtime精准获取电池电量

    http://www.jianshu.com/p/11c1afdf5415

    网络流量

    https://github.com/QbsuranAlang/GetNetworkFlow/blob/master/GetNetworkFlow/GetNetworkFlow/ViewController.m

    2015.11.24

    经测试,mach方法获取的内存值与top命令拿到的RSS、VSS是一致的

  • 相关阅读:
    今天 弄了一下ajax 里面的
    重修理解了一下js 控制treeview 菜单的子级和父级的关系 理解的还不够全 因为 html不够全 但是加个注释吧
    xml .net 用法
    这几天在做把数据库里的数据 导出 并且压缩 学到了一些东西
    今天实现了用按钮后台动态实现了 table里面内容的显示和隐藏 在实现过程中了解了updatepanel的简单的用法
    今天第一次参加了软件产品的讨论会议 收获
    收藏个debug的文章
    Animate.css
    flash遨游缓存问题
    URL短地址压缩算法 微博短地址原理解析 (Java实现)
  • 原文地址:https://www.cnblogs.com/mobilefeng/p/4977783.html
Copyright © 2020-2023  润新知