iOS随笔

获取CPU占用量

 

#import <mach/mach.h>    
    kern_return_t kr;
    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);
    float tot_cpu = 0;
    for (int 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);
        basic_info_th = (thread_basic_info_t)thinfo;
        if (!(basic_info_th->flags & TH_FLAGS_IDLE)) {
            // cpu_usage : Scaled cpu usage percentage. The scale factor is TH_USAGE_SCALE.
            //宏定义TH_USAGE_SCALE返回CPU处理总频率:
            tot_cpu += basic_info_th->cpu_usage / (float)TH_USAGE_SCALE;
        }
    }
    // 注意方法最后要调用 vm_deallocate,防止出现内存泄漏
    kr = vm_deallocate(mach_task_self(), (vm_offset_t)thread_list, thread_count *sizeof(thread_t));
    return tot_cpu;

 

 

内存占用

    task_vm_info_data_t vmInfo;
    mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
    kern_return_t kernelReturn = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count);
    int64_t memoryUsageInByte = (int64_t) vmInfo.phys_footprint;
    return (NSInteger)(memoryUsageInByte/1024/1024);

 

@property

sythesize:自动生成setter和getter方法,且可指定名称的成员变量 

dynamic: 需手动生成setter和getter方法

KVC底层实现原理

1、首先搜索setKey:方法.(key指成员变量名, 首字母大写)

2、上面的setter方法没找到, 如果类方法accessInstanceVariablesDirectly返回YES. 那么按 _key, _isKey,key, iskey的顺序搜索成员名.(NSKeyValueCodingCatogery中实现的类方法, 默认实现为返回YES)

3、如果没有找到成员变量, 调用setValue:forUnderfinedKey:

GET&POST

对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);

而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

UIScrollView滚动:

向上滚动scrollview,我们就不断增加scrollview的bounds的y值,也就是不断把scrollview的本地坐标系原点向下偏移(相对于scrollview的父view的坐标系,y值越大,越向下偏移)。那么此时scrollview的子控件的frame设置的(0,0)就是不断向上偏移

开发证书签名加密过程:

主要涉及以下几个关键步骤:

生成密钥对(生成电脑本地公钥, 私钥在电脑keychain中) 

• 开发者使用钥匙串访问工具在本地生成一对密钥,即公钥和私钥。私钥会被安全地存储在开发者的本地设备钥匙串中,公钥则用于后续的证书申请等操作。

获取证书(用apple私钥加密 电脑公钥, 生成证书)

• 开发者在苹果开发者中心创建证书请求,将公钥等信息包含在证书请求文件(.certSigningRequest)中上传。苹果服务器验证开发者身份等信息后,用苹果的根证书私钥对开发者的公钥等信息进行签名,生成开发证书,其中包含开发者公钥、证书有效期、证书用途等信息。

签名过程(用电脑本地私钥加密ipa文件,哈希,再加密)

• 当开发者使用Xcode构建并归档应用时,Xcode会使用开发者的私钥对应用中的可执行文件、资源等进行签名。计算这些内容的哈希值,再用私钥对哈希值进行加密,生成签名数据,将签名数据与应用程序包一起存储。

验证过程(用apple公钥解密证书文件,获取电脑本地公钥,用公钥解密验证ipa包)

• 设备在安装和运行应用时,系统会获取应用的签名数据和开发者证书。用苹果根证书的公钥验证开发者证书的签名,确认证书是否由苹果颁发且未被篡改。

• 系统从开发者证书中获取开发者公钥,用此公钥解密应用的签名数据,得到原始的哈希值。同时,系统再次计算应用内可执行文件和资源的哈希值,将两个哈希值进行对比,若一致则说明应用未被篡改且来源可靠,可安全运行。

load & initialize

load:

当类被引用进项目的时候(类文件加载到系统中)就会执行load函数(在main函数开始执行之前),与这个类是否被用到无关,每个类的load函数只会自动调用一次.由于load函数是系统自动加载的,因此不需要调用父类的load函数,否则父类的load函数会多次执行。

  • 1.当父类和子类都实现load函数时,父类的load方法执行顺序要优先于子类
  • 2.当子类未实现load方法时,不会调用父类load方法
  • 3.类中的load方法执行顺序要优先于类别(Category)
  • 4.当有多个类别(Category)都实现了load方法,这几个load方法都会执行,但执行顺序不确定(其执行顺序与类别在Compile Sources中出现的顺序一致)
  • 5.当然当有多个不同的类的时候,每个类load 执行顺序与其在Compile Sources出现的顺序一致
initialize:
initialize在类或者其子类的第一个方法被调用前调用。即使类文件被引用进项目,但是没有使用,initialize不会被调用。由于是系统自动调用,也不需要再调用 [super initialize] ,否则父类的initialize会被多次执行。假如这个类放到代码中,而这段代码并没有被执行,这个函数是不会被执行的。
  • 1.父类的initialize方法会比子类先执行
  • 2.当子类未实现initialize方法时,会调用父类initialize方法,子类实现initialize方法时,会覆盖父类initialize方法.
  • 3.当有多个Category都实现了initialize方法,会覆盖类中的方法,只执行一个(会执行Compile Sources 列表中最后一个Category 的initialize方法)

instrument:

Time Profiler:CPU分析工具分析代码的执行时间。

Core Animation:离屏渲染,图层混合等GPU耗时。

1、"Color Blended Layers":图层混合

2、"Color Hits Green and Misses Red":图层缓存

3、"Color Offscreen-Rendered Yellow":离屏渲染

Leaks:内存检测,内存泄漏检测工具。

Allocation: 内存分配情况

Zombie: 野指针检测

NSHashTable:

NSHashTable是比NSSet更通用的一个相似物。NSHashTable相对于NSSet/NSMutableSet有如下特征:
NSSet/NSMutableSet对其对象是强引用,使用isEqual方法去检查对象是否相等,使用方法hash去获取hash值。
NSHashTable是可变的,没有一个不变的和其对应。
NSHashTable可以对其对象是weak引用。当对象被销毁的时候自动将其从集合中移除。
NSHashTable可以在输入(加入)的时候copy对象。
NSHashTable可以包含任意指针,NSHashTableObjectPointerPersonality:和NSPointerFunctionsObjectPointerPersonality相同,此选项是直接使用指针进行isEqual:和hash。

NSMapTabel:

NSMapTable和NSDictionary相对应,相对于NSDictionary/NSMutableDictionary,NSMapTable有如下的特征: NSDictionary/NSMutableDictionary会copy对应的key,强引用相应的value。
NSMapTable是可变的,没有一个不变的类与其对应。
NSMapTable可以对其key和value弱引用,在这种情况下当key或者value被释放的时候,此entry会自动从NSMapTable中移除。
NSMapTable在加入一个(key,value)的时候,可以对其value设置为copy。
NSMapTable可以包含任意指针,NSMapTableObjectPointerPersonality:此选项是直接使用指针进行isEqual:和hash。

yycache:

异步释放缓存对象:把对象捕获到 block 中,然后扔到后台队列去随便发送个消息以避免编译器警告,就可以让对象在后台线程销毁了。

锁的选择,memorycache使用互斥锁,diskCache使用信号量

使用 NSMapTable 单例管理的 YYDiskCache: 

YYKVStorage 中的 _dbStmtCache:省去一些重复生成 sqlite3_stmt 的开销

甚至使用 CoreFoundation 来换取微乎其微的性能提升

memoryCache中使用双链表的结构存储数据,并用dictionary保证了查找速度

采用LRU来优化内存空间

diskCache中根据数据大小,对于大数据采用文件缓存,并将文件名存入到sql中。小数据直接存入到sql中

锁:

atomic: 内部采用了优化过性能的spinlock_t 自旋锁,内部实现为互斥锁。单独的原子操作绝对是线程安全的,但是组合一起的操作就不能保证。
    self.intSource = 0;

    dispatch_async(queue1, ^{
      for (int i = 0; i < 10000; i++) {
          self.intSource = self.intSource + 1;
      }
    });

    dispatch_async(queue2, ^{
      for (int i = 0; i < 10000; i++) {
          self.intSource = self.intSource + 1;
      }
    });
自旋锁:自旋锁在无法进行加锁时,会不断的进行尝试,一般用于临界区的执行时间较短的场景,不过iOS的自旋锁OSSpinLock不再安全,主要原因发生在低优先级线程拿到锁时,高优先级线程进入忙等(busy-wait)状态,消耗大量 CPU 时间,从而导致低优先级线程拿不到 CPU 时间,也就无法完成任务并释放锁。这种问题被称为优先级反转。
互斥锁:对于某一资源同时只允许有一个访问,无论读写,平常使用的NSLock就属于互斥锁
读写锁:对于某一资源同时只允许有一个写访问或者多个读访问,iOS中pthread_rwlock就是读写锁
条件锁:在满足某个条件的时候进行加锁或者解锁,iOS中可使用NSConditionLock来实现
递归锁:可以被一个线程多次获得,而不会引起死锁。它记录了成功获得锁的次数,每一次成功的获得锁,必须有一个配套的释放锁和其对应,这样才不会引起死锁。只有当所有的锁被释放之后,其他线程才可以获得锁,iOS可使用NSRecursiveLock来实现
@synchronized(obj): 内部采用hash算法找到SyncData,并采用的是SyncData.mutext 递归锁
if (obj) {
    SyncData* data = id2data(obj, ACQUIRE);// 一个简单的Hash算法,然后将传入的对象地址,通过地址找到下标映射到不同的SyncList上。而SyncList是一个维护SyncData的链表,每个SyncList都单独维护操作自己的散列锁lock。
    assert(data);
    data->mutex.lock();
}

typedef struct SyncData {
    struct SyncData* nextData;
    DisguisedPtr<objc_object> object;
    int32_t threadCount;  // number of THREADS using this block
    recursive_mutex_t mutex;// 一把递归锁
} SyncData; 
 
posted @ 2020-03-18 15:45  程石亮  阅读(412)  评论(0编辑  收藏  举报