性能测试相关概念
并发用户数(VU): 系统同时处理的request/事务数
QPS(TPS)(transaction per second):每秒钟处理request/事务 数量
响应时间rt: 一般取平均响应时间
这三个参数是一组,理论上,并发数=QPS*rt,当QPS*rt<并发数 时,这时的压力就接近系统所能承受的最大压力了,也就是接近了系统瓶颈。
cpu使用率:cpu被占用的情况,一般要保证在75%以下
load:系统平均负载,被定义为在特定时间间隔(1m,5m,15m)内运行队列中的平均进程数。
前后优化耗时:
1. 慎用try-catch,尤其是在循环之中,可以的话将其移到循环之外。循环内110ms,循环外62ms
2. 多用局部变量。由于局部变量在栈中,其它如静态变量的多在堆中,相比之下变量在栈中会更优秀一些。使用static变量266ms,使用局部变量78ms。
3.位运算代替乘、除法。原219ms,位运算后31ms。
4.switch在循环中可以用数组代替(书中理论)。比较有意思的是我的本机上跑循环中switch耗时8ms,用map/array替代耗时32ms。
5.提取公共表达式。提取前156ms,提取后78ms。
6.展开循环,拉开迭代器增长步长。有必要说一下,这会导致可读性变差,也是没有办法的办法才这么搞。优化前94ms,优化后31ms。
7.静态static方法代替实例方法。
并发过程的优化,这里也是有优化策略的。首先由于数据同步,并发结构需要更改如下:
List : Collections.synchronizedList(List)
Set : Collections.synchronizedList(Set)
HashMap : concurrentHashMap
Queue : concurrentLinkedQueue
volatile : 变量其它线程可见
synchronized : 锁方法,内部锁
ReadWriteLock : 重入锁
ThreadLocal : 局部变量,每个变量一个副本
semaphore :信号量,指定多个线程同时访问某一资源
关于锁,有以下几种方法:
1. 减小锁的范围,举个例子,如果某条记录操作数据库,如果可以将这条记录锁住,那就千万不要用锁整个数据库的方式,而使用将这条记录锁住。
2.减小锁粒度。如concurrentHaspMap结构,其内部是分为16段的,减少Hash时冲突问题。当然这也存在一个问题,就是concurrentHaspMap作为全局使用时,需要获取全部的16个锁。
3.锁分离。LinkedBlockingQueue,基于链表前端、尾端同时操作;此外读写分离锁(针对读多写少的情况)也是这个思想。
4.锁粗化:循环内频繁使用锁时,放在循环之外。
nGrinder
http://blog.csdn.net/neven7/article/details/50740018
Android 性能测试总结
启动时间
启动时间一般我们会测试三种情况。
首次启动
非首次启动
activity 切换所消耗的时间
测试方法一般使用两种:
1、程序内部打点到logcat,手动操作后获取log日志,来获取相应的时间。
2、使用adb 命令来操作,在操作的前后分别记录消耗的时间。(由于adb 操作可能会有延时等可能,此方法并不是很准确)
ps. 还有一种方式是采用告诉摄像机的方式来做,由于本人没有接触过,不过多说明。
1、获取cpu数据
adb shell dumpsys cpuinfo |grep$package_name
输出格式为;
45% TOTAL:18%user+ 20% kernel +6.2% iowait +0.2% softirq
可取total得值作为整体cpu利用率。
2、获取内存数据
adb shell dumpsys meminfo |grep$package_name
或者
adbshell dumpsys meminfo$package_name
直接dumpsys meminfo $package_name 可以看到比较完整的堆,线程,java等级别的内存数据,pss 可以作为内存的参考。
2、使用top 同时获取cpu和内存,-d 参数指定采样数据的间隔时间。
adb shell top-d2
输出:
PIDPR CPU% S#THR VSS RSS PCY UID Name
名词解释:
VSS- Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
RSS- Resident Set Size 实际使用物理内存(包含共享库占用的内存)
PSS- Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
USS- Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)
一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS
可以看到,top 命令取出的内存对应是vss 和 rss,其中rss会比pss稍大,如果没有特别严格的要求,只是对比内存是否泄漏上涨等问题,rss也可以作为参考。
1、通过tcpdump抓包,然后wireshark 解包信息,来获取流量数据。
2、通过adb 命令来获取,先获取应用的pid,然后通过/proc/uid_stat/uid/下的文件来读取流量值。此方式会有rom兼容性问题,并不是所有的文件都可以找到这两个文件。
adbshelldumpsys$package_nameadbshellcat/proc/uid_stat/uid/tcp_rcv -- 下载流量adbshellcat/proc/uid_stat/uid/tcp_snd -- 上传流量
由于tcp_rcv, tcp_snd 的值是一个累加的值,想要获取两次操作间消耗的流量,可以在操作前和操作后分别获取,差值即为期间消耗的流量。也可以每个一段时间做采样,来获取整个过程中的使用情况。
帧率一定程度上反应的是app在使用中的流畅程度,理想情况是每秒60帧。
1、在开发者选项中有个“ GPU呈现模式分析(Profile GPU rendering,计算adb shell dumpsys gfxinfo中的呈现时间)”功能,在开启这个功能后,系统就会记录保留每个界面最后128帧图像绘制的相关时间信息。在开启这个功能后,重新启动APP,滑动页面然后执行adb命令。
adbshell dumpsys gfxinfo$package_name
输出结果中包含这部分数据
DrawProcessExecute1.301.250.530.630.621.640.240.510.440.251.760.400.251.550.430.250.530.370.491.512.12
Draw: 表示在Java中创建显示列表部分中,OnDraw()方法占用的时间。
Process:表示渲染引擎执行显示列表所花的时间,view越多,时间就越长。
Execute:表示把一帧数据发送到屏幕上排版显示实际花费的时间。其实是实际显示帧数据的后台缓存区与前台缓冲区交换后并将前台缓冲区的内容显示到屏幕上的时间。
Draw + Process + Execute = 完整显示一帧 ,这个时间要小于16ms才能保存每秒60帧。
2、通过SurfaceFlinger, 这种方式还没有研究过,过段时间再来补充
adb shell dumpsys SurfaceFlinger
1、对于电量的测试没有什么特别好的方式,可以选择使用物理设备来测试电池的电量情况。
2、对于android 5.0 以上的系统,adb命令可以支持获取电量信息。
adbshelldumpsysbattery
输出内容如下:
ACpowered:falseUSBpowered:trueWirelesspowered:falsestatus:1#电池状态:2:充电状态 ,其他数字为非充电状态health:2present:truelevel:55#电量: 百分比scale:100voltage:3977currentnow:-335232temperature:335#电池状态technology:Li-poly
网友评论