保护你的crash

如何去衡量一款应用的质量好坏?为了回答这一问题,APM这一目的性极强的工具向开发顺应而生。最早的APM开发只关注于crash、cpu这类的硬性指标。而随着移动开发市场的成熟,越来越多的数据指标也被加入到了APM的采集范畴中,包括感官体验相关的数据和使用习惯等。 然而,无论APM最终如何发展,其最核心的采集指标一定是crash数据。一套完善的crash监控方案可以快速的发现并协助完成问题定位,从而能够及时止损,避免更多的损失。而反过来说,如果crash不能及时被发现,又或者因为采集链中出现异常导致了数据丢失,对于开发者和公司来说,这都会是一个噩梦。 crash采集 细分之下,crash分别存在mach exception、signal以及NSException三种类型,每一种类型表示...
Click to read more ...

生产者消费者

在计算机世界当中,数据在不断产生的同时,也在不停地被处理着。产生数据的一方被我们称作生产者,而另一方则被称为消费者。在网络请求中,服务器是提供数据的生产者,而用户是数据的消费者。伴随着互联网的高速发展,即便是百万乃至千万用户级的访问量也并非罕见,而服务器在面临如此高的并发请求时仍能做到游刃有余。这背后的技术并不是三言两语能够说清的,但其中关系着一个重要的模式——生产者-消费者模式 生产者-消费者模式是通过增加缓冲区来平衡生产者和消费者的速率差问题。生产者和消费者彼此不直接通信,通过缓冲区来完成任务 打个比方,以前肯德基的点餐员在点餐之后会顾客配好餐,然后再结账。这种时候,后排的人总是要等到前排完成所有的环节之后才能开始点餐,而现在用户点完餐只需要等待叫号取餐。取餐区就是肯德...
Click to read more ...

线程安全

多线程技术对于计算机开发带来了巨大的性能提升,同样也来带了新的伤痛——线程安全问题。在开发中,稍不注意,我们就可能写出让代码陷入不安全的境地,线程锁是一种用来帮助我们保护临界资源的手段。事实上,现代语言提供了多种不同的线程锁来保护代码。通过深入挖掘,可以发现线程锁的核心无非是Compare and Set,基于这简单的核心,衍化出了多种安全方案,本文就来讲讲锁的原理 数据破坏 在理解如何保障临界代码的安全之前,我们需要了解数据为什么在多线程环境下被破坏。以简单的i++为例,这句代码将i自增一次,在编译成汇编代码后实际上会有三步操作: movl -0x24(%rbp), %r8d addl $0x1, %r8d movl %r8d, -0x24(%rbp) 完成一次i++总共分为...
Click to read more ...

伪单例设计

首先,本文大概率并非实用性文章,即是说你读了本文基本不会带来任何技术上的提升。纯粹出于笔者学习过程中发现的有趣的知识点,然后结合这些技术点的尝试的总结。 何谓伪单例设计 即实现了与单例相同的功能,但是却和正常开发中的单例有着不一样的代码设计。虽然严格的按照单例思想来看的话,两种设计都能被称作单例,但是为了区分两者,我称这种方式为伪单例设计。本文中涉及到两种伪单例设计方案,包括extern和弱符号两种方式。 extern extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。 extern是一个非常有趣的修饰符,允许我们在不依赖某个文件或者外部模块的情况下使用这些外部的函数或者变量。也就是说在...
Click to read more ...

卡顿方案思考

回顾市面上大多数的开源监控方案,大多采用ANR这种机制下的做法去实现卡顿的监控,进而进行堆栈信息的追溯采集等。ANR这种方案最大的优点在于采集数据的准确率很高,基本可以说一旦发现主线程被block住了,那是一抓一个准的。但是同样也有着自己的缺陷,即ping的周期阈值的问题。 目前多数的做法是在子线程中周期性的ping主线程判断主线程是否被堵塞。如果不能在阈值内ping成功,说明主线程已经发生了卡顿 因此,此方案的问题在于这个ping周期应该是多长。本身在实现一套性能监控体系时,我们必须去衡量导入这个工具会带来怎样的损耗,因此这个周期不能太短。同样的,太长的周期也必然会漏掉可能发生的卡顿现象,而且这个概率不低。 平滑度 最近出现了一个称作平滑度的概念,通过应用使用前后的平滑...
Click to read more ...

GCD类型解密

GCD是一套强大的多线程方案,提供了多种任务队列来提高开发效率,通过阅读libdispatch的源码可以更好的理解GCD的工作流程,帮助我们设计更好的代码 结构类型 模板结构 libdispatch使用宏定义实现了大量的模板结构类型,除此之外还使用了union和enum结合的方式实现动态参数类型的灵活性: queue_type:队列类型,例如全局队列 source_type:资源统称,queue或者function都可以看做是一个资源 semaphore_type:信号类型,信号可以保证资源同时多线程竞争下的安全 continuation_type:派发任务会被封装成dispatch_continuation_t,然后被压入队列中 e...
Click to read more ...

资源使用

应用性能的衡量标准有很多,从用户的角度来看,卡顿是最明显的表现,但这不意味看起来不卡顿的应用就不存在性能问题。从开发角度来看,衡量一段代码或者说算法的标准包括空间复杂度和时间复杂度,分别对应内存和CPU两种重要的计算机硬件。只有外在与内在都做没问题,才能说应用的性能做好了。因此,一套应用性能监控系统对开发者的帮助是巨大的,它能帮助你找到应用的性能瓶颈。 CPU 线程是程序运行的最小单位,换句话来说就是:我们的应用其实是由多个运行在CPU上面的线程组合而成的。要想知道应用占用了CPU多少资源,其实就是获取应用所有线程占用CPU的使用量。结构体thread_basic_info封装了单个线程的基本信息: struct thread_basic_info { time_val...
Click to read more ...