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 \n", 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\n", 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\n", 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是一致的

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM