CPU有大小之分、系统会自动调配。javascript
查看CPU:php
$ adb shell top -n 1 -m 10 -d 1 * daemon not running. starting it now on port 5037 * * daemon started successfully * User 6%, System 23%, IOW 0%, IRQ 0% User 8 + Nice 0 + Sys 29 + Idle 88 + IOW 0 + IRQ 0 + SIRQ 0 = 125 PID PR CPU% S #THR VSS RSS PCY UID Name 7543 0 16% R 1 1344K 568K shell top 212 2 9% S 8 12816K 3032K root /system/bin/netd 1043 0 4% S 95 663500K 81248K fg system system_server 6484 0 2% S 20 532780K 46148K bg u0_a82 com.coomix.app.bus 1832 0 0% S 6 7304K 640K root /system/bin/mpdecision 26896 0 0% S 1 0K 0K root kworker/0:0H 206 0 0% S 1 1072K 388K system /system/bin/servicemanager 227 0 0% S 1 944K 408K system /system/bin/qrngd 3 0 0% S 1 0K 0K root ksoftirqd/0 30 1 0% S 1 0K 0K root smsm_cb_wq
-m 10 表示查看使用CPU最多的是个进程。css
User 8 + Nice 0 + Sys 29 + Idle 88 + IOW 0 + IRQ 0 + SIRQ 0 = 125
上面表示每种状态消耗的时间(10s内,单位ms),最大值是100×CPU个数。html
$ adb shell dumpsys cpuinfo Load: 17.55 / 18.49 / 20.27 CPU usage from 10958ms to 955ms ago with 99% awake: 19% 1043/system_server: 17% user + 1.1% kernel / faults: 453 minor 16% 212/netd: 2% user + 14% kernel / faults: 2354 minor 8.5% 2885/dnsmasq: 0.9% user + 7.6% kernel 5.1% 10968/com.coomix.app.bus: 2.7% user + 2.4% kernel / faults: 135 minor 1.4% 227/qrngd: 0% user + 1.4% kernel 0.8% 3/ksoftirqd/0: 0% user + 0.8% kernel 0.6% 11016/com.coomix.app.bus:remote: 0.4% user + 0.2% kernel / faults: 34 minor 0.5% 131/w1_bus_master1: 0% user + 0.5% kernel 0.5% 1832/mpdecision: 0% user + 0.5% kernel 0.4% 1804/mcd: 0.3% user + 0.1% kernel 0.3% 1326/com.android.phone: 0.2% user + 0.1% kernel 0% 7/kworker/u:0H: 0% user + 0% kernel 0.1% 151/mmcqd/0: 0% user + 0.1% kernel 0% 205/healthd: 0% user + 0% kernel 0% 207/vold: 0% user + 0% kernel 0% 226/thermal-engine: 0% user + 0% kernel 0.1% 281/sdcard: 0% user + 0.1% kernel 0% 387/xtwifi-client: 0% user + 0% kernel 0% 1113/com.android.systemui: 0% user + 0% kernel / faults: 1 minor 0% 1375/com.miui.whetstone: 0% user + 0% kernel 0% 1533/com.miui.powerkeeper:service: 0% user + 0% kernel / faults: 10 minor 0% 1983/com.lbe.security:service: 0% user + 0% kernel / faults: 1 minor 0.1% 2061/com.lbe.security.miui: 0% user + 0.1% kernel 0% 2566/com.miui.securitycenter: 0% user + 0% kernel 0% 5518/kworker/0:0: 0% user + 0% kernel 0% 8118/kworker/0:1: 0% user + 0% kernel 0% 21358/kworker/0:4: 0% user + 0% kernel 0% 26896/kworker/0:0H: 0% user + 0% kernel 0.1% 28973/kworker/u:3: 0% user + 0.1% kernel 50% TOTAL: 23% user + 24% kernel + 1.5% softirq
第一行为过去的1,5和15分钟内的平均CPU负载。而后时近7秒全部应用CPU使用状况。java
真实用户测量(RUM Real User Measurement): 收集应用的运行时数据,汇总的结果,输出报告和寻找数据中可能出现的问题。android
有些公司本身开发RUM。若是不能本身开发,市面也有一些免费或者收费的工具。git
集成SDK:github
咱们这里安装了:web
Crashlytic:成立于2011年,是专门为移动应用开者发提供的保存和分析应用崩溃信息的工具。算法
Crittercism:提供了世界上首个领先的移动应用性能管理(mAPM)解决方案。其SDK被嵌入了成千上万的应用中,在全世界有近十亿用户。该公司致力于收集性能数据,例如错误报告、崩溃诊断细节、面包屑(breadcrumbs,指导航记录)、设备/载体/OS统计和用户行为等。这些数据大部分是非结构化的,而且随着应用程序、版本、设备和使用模式的不一样变化很大。
Google分析(Google Analytics): 由Google所提供的网站流量统计服务。
NewRelic: 参考资料:https://en.wikipedia.org/wiki/New_Relic。
另外国内的听云作得也不错,虽然技术比不上国外同行,可是网络相对比较快捷点。对数据安全等要求比较高的,建议不要使用听云。
好比显示图片的方法:
imageViews=new ImageView[100]; public int Imagelooper(int numberofaddedimages, int totalImageCount, RelativeLayout rl){ for(int i=0;i<numberofaddedimages;i++) { totalImageCount = totalImageCount++; //for analytics I want to track crashes.. so lets force it to crash // if(totalImageCount ==100){ // totalImageCount=0; // } //if totalImageCount reaches 100 the app crashes since I have exceeded the array size imageViews[totalImageCount]=new ImageView(this);
若是数据越界达到100,日志报错以下:
03-13 14:01:32.351 13772-13837/com.sillars.imagescroll I/image downloaded? number: 99 03-13 14:01:32.469 13772-13837/com.sillars.imagescroll I/ImageDownloader? image99responsetime (2RTT): 38 03-13 14:01:34.637 13772-13772/com.sillars.imagescroll E/AndroidRuntime? FATAL EXCEPTION: main Process: com.sillars.imagescroll, PID: 13772 java.lang.ArrayIndexOutOfBoundsException: length=100; index=100 at com.sillars.imagescroll.MyActivity.Imagelooper(MyActivity.java:327) at com.sillars.imagescroll.MyActivity$3.onScrollStopped(MyActivity.java:178) at com.sillars.imagescroll.MyScrollView$1.run(MyScrollView.java:37) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:899) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 03-13 14:01:35.329 13772-13797/com.sillars.imagescroll I/Fabric? Crashlytics report upload complete: 550346640083-0001-35CC-27DD9B9DA026.cls 03-13 14:01:54.291 13772-15861/com.sillars.imagescroll I/com.newrelic.agent.android? Harvester: connected 03-13 14:01:54.291 13772-15861/com.sillars.imagescroll I/com.newrelic.agent.android? Harvester: Sending 102 HTTP transactions. 03-13 14:01:54.291 13772-15861/com.sillars.imagescroll I/com.newrelic.agent.android? Harvester: Sending 1 HTTP errors. 03-13 14:01:54.292 13772-15861/com.sillars.imagescroll I/com.newrelic.agent.android? Harvester: Sending 0 activity traces. 03-13 14:02:05.070 13772-13772/com.sillars.imagescroll I/Process? Sending signal. PID: 13772 SIG: 9
Crashalytics的报告以下:
详情参见:http://crashes.to/s/5ba7d984fe7。
New Relic还能够针对具体的HTTP代码进行分析,以下:
Google Analytics能够分析用户行为:
咱们进行分页,也能够从用户的退出看出问题:
/initialize tracker at top of the screen t = analytics.newTracker(R.xml.app_tracker); // Enable Advertising Features. t.enableAdvertisingIdCollection(true); t.enableExceptionReporting(true); t.setScreenName("top of scroll"); t.send(new HitBuilders.ScreenViewBuilder().build()); <snip> //10 more images were just requested, so update the screen name in Google Analytics t.setScreenName(totalImageCount + " images"); t.send(new HitBuilders.ScreenViewBuilder().build()); //and add a crittercism Breadcrumb Crittercism.leaveBreadcrumb(totalImageCount + " images")
增长网络分析:
t.send(new HitBuilders.EventBuilder() .setCategory("RTT Event") .setValue(AvgRTT.longValue()) .setAction("ImageRTT").setLabel(networkConnection).build()); Crittercism.beginTransaction(networkConnection); Crittercism.setTransactionValue(networkConnection, AvgRTT.intValue()); Crittercism.endTransaction(networkConnection);
最后,要注意sdk自己的性能。
无线链接时,功耗从4.5mA增大125 mA。 Wi-Fi 240mA。可是无线链接的服务质量保证开销大,实际耗电更多。Nexus 6的Wi-Fi开启链接3mA,发送数据240 mA。
注意通话时对流量会有影响。
Wireshark是强大的抓包工具,在windows下配合Connectify使用,能够放出wifi来抓包。
Fiddler是一个HTTP代理,能够查看HTTPS流量,可是不能解开HTTPS的文件和内容。
MITMProxy和Fiddler相似, 用法参见:https://mitmproxy.org/doc/mitmproxy.html
应用程序资源优化(ARO Application Resource Optimizer)是监控Android和iOS的应用网络性能的工具。这是来自AT&T的免费/开源工具,它包含许多和Wireshark的和Fiddler相同的数据包捕获功能。且能够收集蜂窝网络数据。
对于Android版本,ARO Data Collector APK在设备上执行tcpdump,须要root权限。若是没有root,也能够运行,可是不能查看进程对应的链接 。
ARO会截取对应的屏幕。缺点,不能解析HTTPS。
对于包含网页的应用,http://www.webpagetest.org/。
网络优化一般是尽量快地下载,而后关闭无线以节省电量。
•减小HTTP请求
•使用CDN(内容分发网络 Content Delivery Network)
•添加一个Expire头
•Gzip组件
•将样式表放在顶部
•脚本放在底部
•避免CSS表达式
•将JavaScript和CSS放在外部文件
•减小DNS查找
•减小JavaScript
•避免重定向
•删除重复的脚本
•配置的ETag
•缓存Ajax
参考资料:http://www.ibm.com/developerworks/cn/web/1308_caiys_jsload/
Gzip是最多见的算法。Zopfli算法比Gzip压缩强5%,可是压缩和解压更耗时,适用于不是常常变的内容。开启压缩,通常在 .htaccess文件:
<ifModule mod_gzip.c>
mod_gzip_on Yes
mod_gzip_dechunk Yes
mod_gzip_item_include file .(html?|txt|css|js|php|pl)$
mod_gzip_item_include handler ^cgi-script$
mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/x-javascript.*
mod_gzip_item_exclude mime ^image/.*
mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</ifModule>
文本文件最小化,好比下面代码:
<html>
<title> A Sample Page</title>
<body>
with some sample text
<--do more here-->
</body>
</html>
修改成:
<html><title> A Sample Page</title><body>with some sample text</body></html>
一般能够减小20-50%。
图片的质量和大小之间要有个合适点。要存储不一样分辨率的图片。要获取图片的MetaData,google的图片一般压缩了85%,要根据不一样的场景使用不一样的压缩。google的WebP格式也能够考虑。
缓存:客户端开启缓存;服务器端设置缓存时间。
Android 4.0及以上版本开启缓存的方法:
private void enableHttpResponseCache() { try { long httpCacheSize = 10 * 1024 * 1024; // 10 MiB File httpCacheDir = new File(getCacheDir(), "http"); Class.forName("android.net.http.HttpResponseCache") .getMethod("install", File.class, long.class) .invoke(null, httpCacheDir, httpCacheSize); } catch (Exception httpResponseCacheNotAvailable) { Log.d(TAG, "HTTP response cache is unavailable."); } }
设备上每一个文件的缓存时间由服务器设置在头部。在缓存时间里,文件直接从cache获取。缓存时间事后,会从新请求并设置缓存时间,若是文件没有修改,则会返回304。控制的方法以下:
缓存控制(添加Expire头):是最经常使用的方法。能够设置Private/Public,多用于CDN;no-store表示不缓存;no-cache:使用以前先验证,实际是有缓存的; max age=X表示缓存时间,单位是秒,一般为 0 (等同于no-cache); 60, 300, 600, 3600 (1 hour),86400 (1 day), 3153600 (1 year)。
ETag或实体标签(entity tag)是万维网协议HTTP的一部分。ETag是HTTP协议提供的若干机制中的一种Web缓存验证机制,而且容许客户端进行缓存协商。这就使得缓存变得更加高效,并且节省带宽。若是资源的内容没有发生改变,Web服务器就不须要发送一个完整的响应。ETag也可用于乐观并发控制,做为一种防止资源同步更新而相互覆盖的方法。
ETag是随机标识符,由Web服务器根据URL上的资源的特定版本而指定,相似于指纹,若是没有修改则返回304了,适用于频繁修改的文件。好比:
HTTP/1.1 200 OK Accept-Ranges: bytes Cache-Control: max-age=86400 Content-Type: image/jpeg Date: Tue, 28 Jan 2014 00:14:55 GMT Etag: "b17ad00-1f17-46723595372c0" Expires: Wed, 29 Jan 2014 00:14:55 GMT Last-Modified: Thu, 09 Apr 2009 18:23:47 GMT Server: Apache/2.2.3 (CentOS) X-Cache: HIT Content-Length: 7959
Expire不如ETag和缓存经常使用。失效时间单位是天。
尽量组合链接数。要尽可能使用已有链接,蜂窝和无线的使用查询:
public static String getNetworkClass(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = cm.getActiveNetworkInfo(); if(info==null || !info.isConnected()) return "-"; //not connected if(info.getType() == ConnectivityManager.TYPE_WIFI) return “wifi"; if(info.getType() == ConnectivityManager.TYPE_MOBILE){ return “cellular"; } } return “unknown"; }
一些动做须要再网络开启的时候再操做,好比:
if (Tel.getDataActivity() >0){ if (Tel.getDataActivity() <4){ //1, 2, 3 response means that the cellular radio is transmitting! //download the image here using image getter imagegetter(counter, numberofimages); //and show the ad AdRequest adRequest = new AdRequest(); adRequest.addTestDevice(AdRequest.TEST_EMULATOR); adView.loadAd(adRequest); // Initiate a generic request to load it with an ad adView.loadAd(new AdRequest()); } }
超过15s不使用的链接,尽可能要关闭。
HttpURLConnection connectionCloseProperly = (HttpURLConnection) ulrn.openConnection(); connectionCloseProperly.setRequestProperty("connection", "close"); //this disables "keep-alive" connectionCloseProperly.setUseCaches(true); connectionCloseProperly.connect(); Object response = connectionCloseProperly.getContent(); InputStream isclose = connectionCloseProperly.getInputStream(); ...download and render bitmap image connectionCloseProperly.disconnect();
内容分发网络(Content delivery network或Content distribution network,缩写:CDN)是指一种经过互联网互相链接的电脑网络系统,提供高性能、可扩展性、及低成本的网络将内容传递给用户。
内容分发网络的总承载量能够比单一骨干最大的带宽还要大。这使得内容分发网络能够承载的用户数量比起传统单一服务器多。也就是说,若把有100Gbps处理能力的服务器放在只有10Gbps带宽的数据中心,则亦只能发挥出10Gbps的承载量。但若是放到十个有10Gbps的地点,整个系统的承载量就能够到10*10Gbps。
同时,将服务器放到不一样地点,能够减小互连的流量,进而下降带宽成本。
对于TCP传输而言,TCP的速度(throughput)会受到延迟时间(latency)与数据包漏失率(packet loss)影响。为了改善这些负面因素,内容分发网络一般会指派较近、较顺畅的服务器节点将数据传输给用户。虽然距离并非绝对因素,但这么作能够尽量提升性能,用户将会以为比较顺畅。这使得一些比较高带宽的应用(传输高清画质的视频)更容易推进。
内容分发网络另一个好处在于有异地备援。当某个服务器故障时,系统将会调用其余邻近地区的服务器服务,进而提供接近100%的可靠度。
除此以外,内容分发网络提供给服务提供者更多的控制权。提供服务的人能够针对客户、地区,或是其余因子调整。
路由控制可使用OpenWrt Linux。Faraday能够用于隔离无线信号。AT&T Network Attenuator 能够模拟各类无线信号:
根据网络类型区分速度:
TelephonyManager teleMan = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); int networkType = teleMan.getNetworkType(); switch (networkType) {case 1: netType = "GPRS"; networkSpeed = "slow"; break; case 2: netType = "EDGE"; networkSpeed = "slow"; break; case 3: netType = "UMTS"; networkSpeed = "medium"; break; // we'll leave out a few network types, but you get the idea. //You can see the full code on Github case 13: netType = "LTE"; networkSpeed = "fast"; break;}
固然上面代码应该考虑信号强度。而后能够根据不一样网络选择不一样的图片:
switch(networkSpeed){ case "fast": new ImageDownloader().execute(urlbig); //image is 143KB break; case "medium": new ImageDownloader().execute(urlmed); //image is 41KB break; case "slow": new ImageDownloader().execute(urlsmall); //image is 27KB break; }
记录下时间:1,服务器返回200的时间;2,下载图片的时间。计算出时延和吞吐量。
private Bitmap downloadBitmap(String url) { Long start = System.currentTimeMillis(); //download start time final DefaultHttpClient client = new DefaultHttpClient(); final HttpGet getRequest = new HttpGet(url); try {HttpResponse response = client.execute(getRequest); //check 200 OK for success final int statusCode = response.getStatusLine().getStatusCode(); Long gotresponse = System.currentTimeMillis(); //time 200 response received } final HttpEntity entity = response.getEntity(); contentlength = entity.getContentLength();//get ContentLength of file if (entity != null) { InputStream inputStream = null; try { inputStream = entity.getContent(); final Bitmap bitmap = BitmapFactory.decodeStream(inputStream); Long gotimage = System.currentTimeMillis(); //time image download completed responsetime = gotresponse - start; //time to the 200 ok response imagetime = gotimage-start; //download time throughput = ((double)contentlength/1024)/((double)imagetime/1000); //KB/s return bitmap; }
高延时的环境,能够先多下载一些图片。
If (latency = normal){ if (ImagesBelowtheFold<2){ <get next batch of images> } } Else { //latency is high if (ImagesBelowtheFold<4){ <get next batch of images> //consider getting more images too //also, smaller images? }
Android 4.4.4之后能够开启Bluetooth HCI snoop log。
强行切换Android M的状态:
adb shell dumpsys battery unplug //tricks the device to stop charging adb shell dumpsys deviceidle step //reusing this step walks you through the various states
Settings → Battery中能够看到应用的电池使用状况。点击具体应用能够查看应用的消耗。点击上部能够查看历史电池消耗状况。能够比较流量和电量的消耗,计算出流量的速率,若是有大量的低速流量,说明设计很差。
Android M中增长了App Standby功能,阻止不经常使用的应用在非充电时链接网络或者发起进程。经过adb shell dumpsys usagestats能够查看使用频率。
安卓4.4之后的adb中增长了batterystats功能。
adb shell dumpsys batterystats --reset adb shell dumpsys batterystats --enable full-wake-history (5.0才支持) adb shell dumpsys batterystats --charged (最近充满以后的电池消耗)
下面部分概述各阶段消耗状况:
Discharge step durations:
#0: +2m28s313ms to 88 (screen-on, power-save-off) #1: +2m38s364ms to 89 (screen-on, power-save-off) #2: +2m27s323ms to 90 (screen-on, power-save-off) #3: +2m8s449ms to 91 (screen-on, power-save-off) #4: +2m17s115ms to 92 (screen-on, power-save-off) #5: +2m7s924ms to 93 (screen-on, power-save-off) #6: +2m17s693ms to 94 (screen-on, power-save-off) #7: +2m6s425ms to 95 (screen-on, power-save-off) #8: +1m50s298ms to 96 (screen-on, power-save-off) #9: +3m0s436ms to 97 (screen-on, power-save-off)
下面部分对电源消耗作了统计:
Statistics since last charge: System starts: 0, currently on battery: false Time on battery: 30m 36s 621ms (99.3%) realtime, 27m 58s 456ms (90.8%) uptime Time on battery screen off: 3m 31s 100ms (11.4%) realtime, 52s 935ms (2.9%) uptime Total run time: 30m 48s 839ms realtime, 28m 10s 674ms uptime Start clock time: 2014-10-17-22-54-33 Screen on: 27m 5s 521ms (88.5%) 1x, Interactive: 27m 5s 837ms (88.5%) Screen brightnesses: dark 27m 5s 521ms (100.0%) Total full wakelock time: 29m 16s 938ms Total partial wakelock time: 17s 153ms Mobile total received: 187.99KB, sent: 201.15KB (packets received 750, sent 742) Phone signal levels: none 35s 29ms (1.9%) 10x poor 11m 7s 494ms (36.3%) 96x moderate 18m 29s 647ms (60.4%) 94x good 24s 451ms (1.3%) 7x Signal scanning time: 0ms
上次充满电后的统计:
Device battery use since last full charge Amount discharged (lower bound): 10 Amount discharged (upper bound): 11
电池使用预计
Estimated power use (mAh): Capacity: 3220, Computed drain: 359, actual drain: 322-354 Uid u0a117: 106 Screen: 96.6 Uid 1000: 26.1 Uid 0: 24.9 Cell standby: 22.9
电池历史统计:
adb bugreport > bugreport.txt //download the output to your computer
./historian.py bugreport.txt > out.html //create the html file
主要建议用安卓5以上版本。分析工具下载地址:https://github.com/google/battery-historian。
JobScheduler在安卓5.0增长,更好地调度任务。
google相关网址
http://developer.android.com/tools/testing/index.html
http://developer.android.com/tools/testing/testing_android.html
http://developer.android.com/tools/testing/testing-tools.html
Top 5 Android Testing Frameworks (with Examples) http://testdroid.com/tech/top-5-android-testing-frameworks-with-examples
googlesamples/android-testing https://github.com/googlesamples/android-testing
Developing Android unit and instrumentation tests - Tutorial http://www.vogella.com/tutorials/AndroidTesting/article.html
Introduction to Android development with Android Studio - Tutorial http://www.vogella.com/tutorials/Android/article.html
Building Android applications with Gradle - Tutorial http://www.vogella.com/tutorials/AndroidBuild/article.html
How Do Top Android Developers QA Test Their Apps? http://techcrunch.com/2012/06/02/android-qa-testing-quality-assurance/
Android Testing Tutorial: Unit Testing like a True Green Droid http://www.toptal.com/android/testing-like-a-true-green-droid
https://www.youtube.com/watch?v=L-k6dpfXqBY
Android Testing Options https://github.com/codepath/android_guides/wiki/Android-Testing-Options