|
|
//
|
|
|
// YH_AppInfoMonitor.m
|
|
|
// YH_Mall
|
|
|
//
|
|
|
// Created by Misty on 2018/8/2.
|
|
|
// Copyright © 2018年 YOHO. All rights reserved.
|
|
|
//
|
|
|
|
|
|
#import "YH_AppInfoMonitor.h"
|
|
|
#import <mach/mach.h>
|
|
|
#include <ifaddrs.h>
|
|
|
#include <net/if.h>
|
|
|
|
|
|
@interface YH_AppInfoMonitor() {
|
|
|
NSTimeInterval lastTime;
|
|
|
NSUInteger count;
|
|
|
BOOL prevValid;
|
|
|
}
|
|
|
|
|
|
@property (nonatomic, strong) CADisplayLink *displayLink;
|
|
|
@property (nonatomic, strong) NSTimer *timer;
|
|
|
@property (nonatomic, copy) void (^monitorBlock)(CGFloat cpuUsage, CGFloat usedMem, CGFloat allMem, CGFloat fpsValue, int64_t sendBytes, int64_t receivedBytes); //每秒获取
|
|
|
|
|
|
@property (nonatomic, assign) CGFloat fpsValue;
|
|
|
@property (nonatomic, assign) int64_t prevWiFiSent;
|
|
|
@property (nonatomic, assign) int64_t prevWiFiReceived;
|
|
|
@property (nonatomic, assign) int64_t prevWWANSent;
|
|
|
@property (nonatomic, assign) int64_t prevWWANReceived;
|
|
|
|
|
|
@property (nonatomic, assign) int64_t WiFiSent;
|
|
|
@property (nonatomic, assign) int64_t WiFiReceived;
|
|
|
@property (nonatomic, assign) int64_t WWANSent;
|
|
|
@property (nonatomic, assign) int64_t WWANReceived;
|
|
|
|
|
|
@end
|
|
|
|
|
|
@implementation YH_AppInfoMonitor
|
|
|
|
|
|
- (instancetype)init {
|
|
|
if ([super init]) {
|
|
|
if (self) {
|
|
|
prevValid = false;
|
|
|
_prevWiFiSent = 0;
|
|
|
_prevWiFiReceived = 0;
|
|
|
_prevWWANSent = 0;
|
|
|
_prevWWANReceived = 0;
|
|
|
|
|
|
_WiFiSent = 0;
|
|
|
_WiFiReceived = 0;
|
|
|
_WWANSent = 0;
|
|
|
_WWANReceived = 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return self;
|
|
|
}
|
|
|
|
|
|
- (void)startMonitorBlock:(void (^)(CGFloat, CGFloat, CGFloat, CGFloat, int64_t, int64_t))block {
|
|
|
self.monitorBlock = block;
|
|
|
|
|
|
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
|
|
|
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
|
|
|
|
|
self.timer = [NSTimer timerWithTimeInterval:self.timeInterval target:self selector:@selector(getAppCollectData) userInfo:nil repeats:YES];
|
|
|
[self.timer fire];
|
|
|
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
|
|
|
|
|
|
}
|
|
|
|
|
|
- (void)stopMonitoring {
|
|
|
[self.displayLink invalidate];
|
|
|
self.displayLink = nil;
|
|
|
|
|
|
[self.timer invalidate];
|
|
|
self.timer = nil;
|
|
|
|
|
|
prevValid = false;
|
|
|
|
|
|
_prevWiFiSent = 0;
|
|
|
_prevWiFiReceived = 0;
|
|
|
_prevWWANSent = 0;
|
|
|
_prevWWANReceived = 0;
|
|
|
|
|
|
_WiFiSent = 0;
|
|
|
_WiFiReceived = 0;
|
|
|
_WWANSent = 0;
|
|
|
_WWANReceived = 0;
|
|
|
}
|
|
|
|
|
|
- (void)getAppCollectData {
|
|
|
CGFloat cpu = [self getCpuUsage];
|
|
|
CGFloat usedMem = [self getMemUsage];
|
|
|
CGFloat allMem = [self getMemAllUsage];
|
|
|
CGFloat fps = self.fpsValue;
|
|
|
|
|
|
[self getNetFlowData];
|
|
|
int64_t nowSent = _WiFiSent + _WWANSent;
|
|
|
int64_t nowRecived = _WiFiReceived + _WWANReceived;
|
|
|
|
|
|
if (self.monitorBlock) {
|
|
|
self.monitorBlock(cpu, usedMem, allMem, fps, nowSent, nowRecived);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
#pragma mark - cpu
|
|
|
//流量消耗
|
|
|
- (CGFloat)getCpuUsage {
|
|
|
return [YH_AppInfoMonitor getCpuUsage];
|
|
|
}
|
|
|
|
|
|
// 获取应用当前的CPU
|
|
|
+ (CGFloat)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(), MACH_TASK_BASIC_INFO, (task_info_t)tinfo, &task_info_count);
|
|
|
if (kr != KERN_SUCCESS) {
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
|
|
// get threads in the task
|
|
|
kr = task_threads(mach_task_self(), &thread_list, &thread_count);
|
|
|
if (kr != KERN_SUCCESS) {
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
long total_time = 0;
|
|
|
long total_userTime = 0;
|
|
|
CGFloat total_cpu = 0;
|
|
|
int j;
|
|
|
|
|
|
// for each thread
|
|
|
for (j = 0; j < (int)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 -1;
|
|
|
}
|
|
|
|
|
|
basic_info_th = (thread_basic_info_t)thinfo;
|
|
|
|
|
|
if (!(basic_info_th->flags & TH_FLAGS_IDLE)) {
|
|
|
total_time = total_time + basic_info_th->user_time.seconds + basic_info_th->system_time.seconds;
|
|
|
total_userTime = total_userTime + basic_info_th->user_time.microseconds + basic_info_th->system_time.microseconds;
|
|
|
total_cpu = total_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));
|
|
|
assert(kr == KERN_SUCCESS);
|
|
|
|
|
|
return total_cpu;
|
|
|
}
|
|
|
|
|
|
#pragma mark - mem
|
|
|
//内存占用
|
|
|
- (CGFloat)getMemAllUsage {
|
|
|
return [YH_AppInfoMonitor allUsedMemory];
|
|
|
}
|
|
|
|
|
|
//内存占用
|
|
|
- (CGFloat)getMemUsage {
|
|
|
return [YH_AppInfoMonitor appUsedMemory];
|
|
|
}
|
|
|
|
|
|
+ (CGFloat)appUsedMemory {
|
|
|
//app 当前的驻留内存
|
|
|
struct mach_task_basic_info info;
|
|
|
mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT;
|
|
|
int r = task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)& info, & count);
|
|
|
if (r == KERN_SUCCESS) {
|
|
|
return info.resident_size;
|
|
|
}
|
|
|
else {
|
|
|
NSParameterAssert(NO);
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ (CGFloat)allUsedMemory {
|
|
|
//app 相关的内存总量,不一定都处于使用状态,可能是未被回收
|
|
|
mach_port_t host_port = mach_host_self();
|
|
|
mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
|
|
|
vm_size_t page_size;
|
|
|
vm_statistics64_data_t vm_stat;
|
|
|
kern_return_t kern;
|
|
|
kern = host_page_size(host_port, &page_size);
|
|
|
if (kern != KERN_SUCCESS) {
|
|
|
NSParameterAssert(NO);
|
|
|
return 0;
|
|
|
}
|
|
|
kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);
|
|
|
if (kern != KERN_SUCCESS) {
|
|
|
NSParameterAssert(NO);
|
|
|
return 0;
|
|
|
}
|
|
|
return page_size * (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count);
|
|
|
}
|
|
|
|
|
|
#pragma mark - fps
|
|
|
|
|
|
- (void)handleDisplayLink:(CADisplayLink *)displayLink {
|
|
|
if (lastTime == 0)
|
|
|
{
|
|
|
lastTime = self.displayLink.timestamp;
|
|
|
return ;
|
|
|
}
|
|
|
count++;
|
|
|
NSTimeInterval timeout = self.displayLink.timestamp - lastTime;
|
|
|
if (timeout < 1)
|
|
|
{
|
|
|
return ;
|
|
|
}
|
|
|
lastTime = self.displayLink.timestamp;
|
|
|
CGFloat fps = count / timeout;
|
|
|
count = 0;
|
|
|
|
|
|
self.fpsValue = fps;
|
|
|
}
|
|
|
|
|
|
#pragma mark - net
|
|
|
- (void)getNetFlowData
|
|
|
{
|
|
|
BOOL success;
|
|
|
struct ifaddrs *addrs;
|
|
|
const struct ifaddrs *cursor;
|
|
|
const struct if_data *networkStatisc;
|
|
|
|
|
|
int64_t WiFiSent = 0;
|
|
|
int64_t WiFiReceived = 0;
|
|
|
int64_t WWANSent = 0;
|
|
|
int64_t WWANReceived = 0;
|
|
|
|
|
|
NSString *name = @"";
|
|
|
|
|
|
success = getifaddrs(&addrs) == 0;
|
|
|
if (success)
|
|
|
{
|
|
|
cursor = addrs;
|
|
|
while (cursor != NULL)
|
|
|
{
|
|
|
name=[NSString stringWithFormat:@"%s",cursor->ifa_name];
|
|
|
|
|
|
// names of interfaces: en0 is WiFi ,pdp_ip0 is WWAN
|
|
|
if (cursor->ifa_addr->sa_family == AF_LINK)
|
|
|
{
|
|
|
if ([name hasPrefix:@"en"]) {
|
|
|
networkStatisc = (const struct if_data *) cursor->ifa_data;
|
|
|
WiFiSent+=networkStatisc->ifi_obytes;
|
|
|
WiFiReceived+=networkStatisc->ifi_ibytes;
|
|
|
}
|
|
|
|
|
|
if ([name hasPrefix:@"pdp_ip"]) {
|
|
|
networkStatisc = (const struct if_data *) cursor->ifa_data;
|
|
|
WWANSent+=networkStatisc->ifi_obytes;
|
|
|
WWANReceived+=networkStatisc->ifi_ibytes;
|
|
|
}
|
|
|
}
|
|
|
cursor = cursor->ifa_next;
|
|
|
}
|
|
|
freeifaddrs(addrs);
|
|
|
}
|
|
|
|
|
|
if (prevValid == true)
|
|
|
{
|
|
|
_WiFiSent = WiFiSent - _prevWiFiSent;
|
|
|
_WiFiReceived = WiFiReceived - _prevWiFiReceived;
|
|
|
_WWANSent = WWANSent - _prevWWANSent;
|
|
|
_WWANReceived = WWANReceived - _prevWWANReceived;
|
|
|
|
|
|
_prevWiFiSent = WiFiSent;
|
|
|
_prevWiFiReceived = WiFiReceived;
|
|
|
_prevWWANSent = WWANSent;
|
|
|
_prevWWANReceived = WWANReceived;
|
|
|
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
prevValid = true;
|
|
|
//记录第一次启动监控的流量
|
|
|
_prevWiFiSent = WiFiSent;
|
|
|
_prevWiFiReceived = WiFiReceived;
|
|
|
_prevWWANSent = WWANSent;
|
|
|
_prevWWANReceived = WWANReceived;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@end |
...
|
...
|
|