性能優(yōu)化,都要優(yōu)化什么稚配?
- 啟動(dòng)時(shí)間
- 內(nèi)存
- 刷新幀率
- UI阻塞次數(shù)奶赠,不可操作時(shí)長(zhǎng),主線程阻塞超過(guò)400毫秒次數(shù)
- CPU使用率
- GPU使用率
- 網(wǎng)絡(luò)請(qǐng)求時(shí)間药有,流量消耗
- 耗電功率
如何去監(jiān)測(cè)這些性能指標(biāo)毅戈。
-
Xcode自帶的Instrument Instrument 用戶指南(中文版)
Instrument 性能檢測(cè)圖譜:
使用第三方SDK :Bugly苹丸、OneAPM、聽(tīng)云苇经、Firebase Analytics
自行開(kāi)發(fā)檢測(cè)代碼
啟動(dòng)時(shí)間
1.通過(guò)Instrument的Time Profiler赘理,找到包含-[UIApplication _reportAppLaunchFinished]的最后一幀,可計(jì)算出啟動(dòng)時(shí)間扇单。
2.自行添加代碼計(jì)算
t1
系統(tǒng)dylib和自身app可執(zhí)行文件(app中所有.o文件的集合)的加載
Launch頁(yè)
t2
main()
UIApplicationMain()
willFinishLaunchingWithOptions()
didFinishLaunchingWithOptions()
t3
loadView()
viewDidLoad()
applicationDidBecomeActive()
啟動(dòng)時(shí)間 t = t1 + t2;
app從啟動(dòng)到打開(kāi)第一個(gè)頁(yè)面的時(shí)間 t = t1 + t2 + t3;
t1:在Xcode的Edit scheme中增加
DYLD_PRINT_STATISTICS這個(gè)環(huán)境變量商模,控制臺(tái)就會(huì)打印這個(gè)時(shí)間。
t2蜘澜、t3都可以通過(guò)埋點(diǎn)的方式添加獲取時(shí)間的代碼即可施流。
內(nèi)存
目前在開(kāi)發(fā)的階段只會(huì)注意內(nèi)存泄露和內(nèi)存異常
兩種情況,具體的內(nèi)存分配鄙信、僵尸對(duì)象等可能會(huì)在開(kāi)發(fā)結(jié)束后進(jìn)行檢測(cè)瞪醋。
內(nèi)存泄露
除了使用instrument,還有:
- 手動(dòng)添加代碼:
- (void)delloc {
NSLog(@"------------->--->%@被釋放了",[self class]);
}
這個(gè)只是說(shuō)明某個(gè)類釋放情況装诡,并不能定位到具體代碼银受,需要在類內(nèi)部進(jìn)行排查。
- 第三方工具M(jìn)LeaksFinder鸦采,優(yōu)點(diǎn):
1.這個(gè)庫(kù)不需要入侵項(xiàng)目代碼宾巍,直接pod導(dǎo)入一下庫(kù)就
2.不用像instruments那么麻煩,還需要自己來(lái)仔細(xì)觀察
3.庫(kù)只在debug狀態(tài)運(yùn)行渔伯,完全不影響app打包大小
內(nèi)存異常
就只是觀察Xcode里面的內(nèi)存顯示或者埋點(diǎn)插入內(nèi)存計(jì)算的方法顶霞,代碼如下:
#import <mach/mach.h>
#import <mach/task_info.h>
- (unsigned long)memoryUsage
{
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
if (kr != KERN_SUCCESS) {
return -1;
}
unsigned long memorySize = info.resident_size >> 10;//10-KB 20-MB
return memorySize;
//返回的數(shù)值單位是KB,如果想要MB的話把10改為20锣吼。
}
刷新幀率
刷新幀率利用CADisplayLink做一個(gè)小工具進(jìn)行檢測(cè)确丢,查看認(rèn)識(shí)并使用CADisplayLink。
UI阻塞次數(shù)吐限,不可操作時(shí)長(zhǎng)鲜侥,主線程阻塞超過(guò)400毫秒次數(shù)
美團(tuán)移動(dòng)端性能監(jiān)控方案Hertz
在實(shí)踐中采用的是檢測(cè)主線程每次執(zhí)行消息循環(huán)的時(shí)間,當(dāng)這一時(shí)間大于閾值時(shí)诸典,就記為發(fā)生一次卡頓描函。
開(kāi)辟一個(gè)子線程,然后實(shí)時(shí)計(jì)算 kCFRunLoopBeforeSources 和 kCFRunLoopAfterWaiting 兩個(gè)狀態(tài)區(qū)域之間的耗時(shí)是否超過(guò)某個(gè)閥值狐粱,來(lái)斷定主線程的卡頓情況舀寓。這個(gè)還是比較準(zhǔn)確的數(shù)據(jù)。
但是由于主線程的RunLoop在閑置時(shí)基本處于Before Waiting狀態(tài)肌蜻,這就導(dǎo)致了即便沒(méi)有發(fā)生任何卡頓互墓,這種檢測(cè)方式也總能認(rèn)定主線程處在卡頓狀態(tài)。
CPU使用率
CPU使用率只需觀察Xcode里面的數(shù)據(jù)或者埋點(diǎn)插入CPU使用率計(jì)算的方法蒋搜,代碼如下:
- (float)cpu_usage
{
kern_return_t kr = { 0 };
task_info_data_t tinfo = { 0 };
mach_msg_type_number_t task_info_count = TASK_INFO_MAX;
kr = task_info( mach_task_self(), TASK_BASIC_INFO, (task_info_t)tinfo, &task_info_count );
if ( KERN_SUCCESS != kr )
return 0.0f;
task_basic_info_t basic_info = { 0 };
thread_array_t thread_list = { 0 };
mach_msg_type_number_t thread_count = { 0 };
thread_info_data_t thinfo = { 0 };
thread_basic_info_t basic_info_th = { 0 };
basic_info = (task_basic_info_t)tinfo; // get threads in the task
kr = task_threads( mach_task_self(), &thread_list, &thread_count );
if ( KERN_SUCCESS != kr )
return 0.0f;
long tot_sec = 0;
long tot_usec = 0;
float tot_cpu = 0;
for ( int i = 0; i < thread_count; i++ )
{
mach_msg_type_number_t thread_info_count = THREAD_INFO_MAX;
kr = thread_info( thread_list[i], THREAD_BASIC_INFO, (thread_info_t)thinfo, &thread_info_count );
if ( KERN_SUCCESS != kr )
return 0.0f;
basic_info_th = (thread_basic_info_t)thinfo;
if ( 0 == (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;
}
}
kr = vm_deallocate( mach_task_self(), (vm_offset_t)thread_list, thread_count * sizeof(thread_t) );
if ( KERN_SUCCESS != kr )
return 0.0f;
return tot_cpu * 100.; // CPU 占用百分比}
具體使用可以使用instrument查看篡撵。
GPU使用率
iOS 設(shè)備跟蹤 GPU 使用率
GPUUtilization GPU使用率檢測(cè)Demo
網(wǎng)絡(luò)請(qǐng)求時(shí)間判莉,流量消耗
該部分在AFNetworking研究之后再做補(bǔ)充。