APP的性能監(jiān)控方案:CPU是嗜、FPS、內(nèi)存

線下監(jiān)控

  • Xcode Instruments
  • 使用 Instruments 的 os_signpost API 來完成自定義的性能數(shù)據(jù)監(jiān)控工具開發(fā)步责。

線上監(jiān)控

原則

  1. 監(jiān)控代碼不要侵入到業(yè)務(wù)代碼中返顺;
  2. 采用性能消耗最小的監(jiān)控方案。

監(jiān)控內(nèi)容

  • CPU使用率
  • FPS幀率
  • 內(nèi)存

CPU使用率

方案

APP對CPU使用率蔓肯,等于APP中所有線程對CPU使用率的總和遂鹊。

在iOS系統(tǒng)中,usr/include/mach/thread_info.h 里可以看到線程基本信息的結(jié)構(gòu)體:

struct thread_basic_info {
  time_value_t    user_time;     // 用戶運行時長
  time_value_t    system_time;   // 系統(tǒng)運行時長
  integer_t       cpu_usage;     // CPU 使用率
  policy_t        policy;        // 調(diào)度策略
  integer_t       run_state;     // 運行狀態(tài)
  integer_t       flags;         // 各種標(biāo)記
  integer_t       suspend_count; // 暫停線程的計數(shù)
  integer_t       sleep_time;    // 休眠的時間
};
實現(xiàn)

使用定時器蔗包,每2s去遍歷所有線程秉扑,累加線程的cpu_usage字段的值,獲得當(dāng)前APP對CPU的使用率调限。


+ (integer_t)cpuUsage {
    thread_act_array_t threads; //int 組成的數(shù)組比如 thread[1] = 5635
    mach_msg_type_number_t threadCount = 0; //mach_msg_type_number_t 是 int 類型
    const task_t thisTask = mach_task_self();
    //根據(jù)當(dāng)前 task 獲取所有線程
    kern_return_t kr = task_threads(thisTask, &threads, &threadCount);
    
    if (kr != KERN_SUCCESS) {
        return 0;
    }
    
    integer_t cpuUsage = 0;
    // 遍歷所有線程
    for (int i = 0; i < threadCount; i++) {
        
        thread_info_data_t threadInfo;
        thread_basic_info_t threadBaseInfo;
        mach_msg_type_number_t threadInfoCount = THREAD_INFO_MAX;
        
        if (thread_info((thread_act_t)threads[i], THREAD_BASIC_INFO, (thread_info_t)threadInfo, &threadInfoCount) == KERN_SUCCESS) {
            // 獲取 CPU 使用率
            threadBaseInfo = (thread_basic_info_t)threadInfo;
            if (!(threadBaseInfo->flags & TH_FLAGS_IDLE)) {
                cpuUsage += threadBaseInfo->cpu_usage;
            }
        }
    }
    assert(vm_deallocate(mach_task_self(), (vm_address_t)threads, threadCount * sizeof(thread_t)) == KERN_SUCCESS);
    return cpuUsage;
}

FPS監(jiān)控

通過注冊 CADisplayLink 得到屏幕的同步刷新率舟陆,記錄每次刷新時間,然后就可以得到 FPS旧噪。


- (void)start {
    self.dLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(fpsCount:)];
    [self.dLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}

// 方法執(zhí)行幀率和屏幕刷新率保持一致
- (void)fpsCount:(CADisplayLink *)displayLink {
    if (lastTimeStamp == 0) {
        lastTimeStamp = self.dLink.timestamp;
    } else {
        total++;
        // 開始渲染時間與上次渲染時間差值
        NSTimeInterval useTime = self.dLink.timestamp - lastTimeStamp;
        if (useTime < 1) return;
        lastTimeStamp = self.dLink.timestamp;
        // fps 計算
        fps = total / useTime; 
        total = 0;
    }
}

內(nèi)存監(jiān)控

WWDC:iOS Memory Deep Dive

phys_footprint是實際使用的物理內(nèi)存吨娜。

內(nèi)存信息存在task_info.h(完整路徑 usr/include/mach/task.info.h)文件的task_vm_info結(jié)構(gòu)體中,其中phys_footprint就是物理內(nèi)存的使用淘钟,而不是駐留內(nèi)存resident_size宦赠。結(jié)構(gòu)體里和內(nèi)存相關(guān)的代碼如下:

struct task_vm_info {
  mach_vm_size_t  virtual_size;       // 虛擬內(nèi)存大小
  integer_t region_count;             // 內(nèi)存區(qū)域的數(shù)量
  integer_t page_size;
  mach_vm_size_t  resident_size;      // 駐留內(nèi)存大小
  mach_vm_size_t  resident_size_peak; // 駐留內(nèi)存峰值

  ...

  /* added for rev1 */
  mach_vm_size_t  phys_footprint;     // 物理內(nèi)存
  ...

類似于對 CPU 使用率的監(jiān)控陪毡,我們只要從這個結(jié)構(gòu)體里取出 phys_footprint 字段的值,就能夠監(jiān)控到實際物理內(nèi)存的使用情況了勾扭。

uint64_t memoryUsage() {
    task_vm_info_data_t vmInfo;
    mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
    kern_return_t result = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count);
    if (result != KERN_SUCCESS)
        return 0;
    return vmInfo.phys_footprint;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毡琉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子妙色,更是在濱河造成了極大的恐慌桅滋,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件身辨,死亡現(xiàn)場離奇詭異丐谋,居然都是意外死亡,警方通過查閱死者的電腦和手機煌珊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門号俐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人定庵,你說我怎么就攤上這事吏饿。” “怎么了蔬浙?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵猪落,是天一觀的道長。 經(jīng)常有香客問我畴博,道長笨忌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任绎晃,我火速辦了婚禮蜜唾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘庶艾。我一直安慰自己袁余,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布咱揍。 她就那樣靜靜地躺著颖榜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪煤裙。 梳的紋絲不亂的頭發(fā)上掩完,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音硼砰,去河邊找鬼且蓬。 笑死,一個胖子當(dāng)著我的面吹牛题翰,可吹牛的內(nèi)容都是我干的恶阴。 我是一名探鬼主播诈胜,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼冯事!你這毒婦竟也來了焦匈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤昵仅,失蹤者是張志新(化名)和其女友劉穎缓熟,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體摔笤,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡够滑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了籍茧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片版述。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖寞冯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情晚伙,我是刑警寧澤吮龄,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站咆疗,受9級特大地震影響漓帚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜午磁,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一尝抖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧迅皇,春花似錦昧辽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至框咙,卻和暖如春咕痛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背喇嘱。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工茉贡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人者铜。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓腔丧,卻偏偏與公主長得像放椰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子悔据,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355