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