2017年6月13日
前言
前幾日在改Bug時看到好多調試時用的日志語句都被一個日志開關控制着它的執行權。形如:
1 if(Constants.LOG_TAG){ 2 Log.d(TAG, "Initialize finish! index:" + idx); 3 }
又為了方便日后遇到問題時的分析,還要加上很多類似的日志語句。這時突然很好奇“大量的”條件判斷語句需要多消耗多少系統資源,以及不同的條件表達式占用系統資源的差異情況。為此,特意設計了一個簡單的小實驗,通過取多組不同環境下這幾種情形的耗時均值作為考量依據。
設計實驗
對指定的條件語句進行一億次的運算,計算運算前后的時間差作為結果。
- 一億次循環運算空跑的耗時情況;
- if語句條件表達式為簡單運算的情況的耗時情況;
- if語句條件表達式為局部boolean且值為true;
- if語句條件表達式為局部boolean且值為false;
- if語句條件表達式為局部final boolean且值為false;
- if語句條件表達式為全局boolean且值為false;
- if語句條件表達式為全局final boolean且值為false;
- if語句條件表達式為另一個類對象中的實例變量boolean且值為false;
- if語句條件表達式為另一個類對象中的靜態變量boolean且值為true;
- if語句條件表達式為另一個類對象中的靜態變量boolean且值為false;
- if語句條件表達式為另一個類對象中的靜態final布爾變量且值為true;
- if語句條件表達式為另一個類對象中的靜態final布爾變量且值為false;
- if語句條件表達式為靜態final變量boolean且值為false;
- if語句條件表達式為靜態變量boolean且值為false;
實驗環境
操作系統:Android 5.1
設備系統:4K智能電視
處理器:Hi3751v620
內存:2GB
代碼設計
MainActivity.java 主要代碼
1 private final String TAG = "chorm"; 2 3 private final int chorm = 100000000;// 1億 4 private boolean fieldBool; 5 private final boolean fieldBool2 = false; 6 private static boolean B3 = false; 7 private final static boolean B4 = false; 8 9 private long getTime() { 10 return SystemClock.uptimeMillis(); 11 } 12 13 public void click(View v) { 14 int counter; 15 16 Log.i(TAG, "- Prebuilt -"); 17 counter = chorm; 18 long start = getTime(); 19 do { 20 counter--; 21 } while (counter > 0); 22 long end = getTime(); 23 24 Log.i(TAG, " - Demo begin -"); 25 // 1. 一億次循環運算空跑的耗時情況; 26 counter = chorm; 27 start = getTime(); 28 do { 29 counter--; 30 } while (counter > 0); 31 end = getTime(); 32 Log.d(TAG, "1:Time spent:" + (end - start) + "ms"); 33 34 // 2. if語句條件表達式為簡單運算的情況的耗時情況; 35 counter = chorm; 36 start = getTime(); 37 do { 38 counter--; 39 if ((9 + 17) == 8) { 40 41 } 42 } while (counter > 0); 43 end = getTime(); 44 Log.d(TAG, "2:Time spent:" + (end - start) + "ms"); 45 46 // 3. if語句條件表達式為局部boolean且值為true; 47 counter = chorm; 48 boolean localBool = true; 49 start = getTime(); 50 do { 51 counter--; 52 if (localBool) { 53 54 } 55 } while (counter > 0); 56 end = getTime(); 57 Log.d(TAG, "3:Time spent:" + (end - start) + "ms"); 58 59 // 4. if語句條件表達式為局部boolean且值為false; 60 counter = chorm; 61 localBool = false; 62 start = getTime(); 63 do { 64 counter--; 65 if (localBool) { 66 67 } 68 } while (counter > 0); 69 end = getTime(); 70 Log.d(TAG, "4:Time spent:" + (end - start) + "ms"); 71 72 // 5. if語句條件表達式為局部final boolean且值為false; 73 counter = chorm; 74 final boolean localBool2 = false; 75 start = getTime(); 76 do { 77 counter--; 78 if (localBool2) { 79 80 } 81 } while (counter > 0); 82 end = getTime(); 83 Log.d(TAG, "5:Time spent:" + (end - start) + "ms"); 84 85 // 6. if語句條件表達式為全局boolean且值為false; 86 counter = chorm; 87 start = getTime(); 88 do { 89 counter--; 90 if (fieldBool) { 91 92 } 93 } while (counter > 0); 94 end = getTime(); 95 Log.d(TAG, "6:Time spent:" + (end - start) + "ms"); 96 97 // 7. if語句條件表達式為全局final boolean且值為false; 98 counter = chorm; 99 start = getTime(); 100 do { 101 counter--; 102 if (fieldBool2) { 103 104 } 105 } while (counter > 0); 106 end = getTime(); 107 Log.d(TAG, "7:Time spent:" + (end - start) + "ms"); 108 109 // 8. if語句條件表達式為另一個類對象中的實例變量boolean且值為false; 110 counter = chorm; 111 AnotherClass ac = new AnotherClass(); 112 start = getTime(); 113 do { 114 counter--; 115 if (ac.bool) { 116 117 } 118 } while (counter > 0); 119 end = getTime(); 120 Log.d(TAG, "8:Time spent:" + (end - start) + "ms"); 121 122 // 9. if語句條件表達式為另一個類對象中的靜態變量boolean且值為true; 123 counter = chorm; 124 start = getTime(); 125 do { 126 counter--; 127 if (AnotherClass.BOOL) { 128 129 } 130 } while (counter > 0); 131 end = getTime(); 132 Log.d(TAG, "9:Time spent:" + (end - start) + "ms"); 133 134 // 10. if語句條件表達式為另一個類對象中的靜態變量boolean且值為false; 135 counter = chorm; 136 start = getTime(); 137 do { 138 counter--; 139 if (AnotherClass.BOOL2) { 140 141 } 142 } while (counter > 0); 143 end = getTime(); 144 Log.d(TAG, "10:Time spent:" + (end - start) + "ms"); 145 146 // 11. if語句條件表達式為另一個類對象中的靜態final變量boolean且值為true; 147 counter = chorm; 148 start = getTime(); 149 do { 150 counter--; 151 if (AnotherClass.BOOL3) { 152 153 } 154 } while (counter > 0); 155 end = getTime(); 156 Log.d(TAG, "11:Time spent:" + (end - start) + "ms"); 157 158 // 12. if語句條件表達式為另一個類對象中的靜態final變量boolean且值為false; 159 counter = chorm; 160 start = getTime(); 161 do { 162 counter--; 163 if (AnotherClass.BOOL4) { 164 165 } 166 } while (counter > 0); 167 end = getTime(); 168 Log.d(TAG, "12:Time spent:" + (end - start) + "ms"); 169 170 // 13. if語句條件表達式為靜態final變量boolean且值為false; 171 counter = chorm; 172 start = getTime(); 173 do { 174 counter--; 175 if (B4) { 176 177 } 178 } while (counter > 0); 179 end = getTime(); 180 Log.d(TAG, "13:Time spent:" + (end - start) + "ms"); 181 182 // 14. if語句條件表達式為靜態變量boolean且值為false; 183 counter = chorm; 184 start = getTime(); 185 do { 186 counter--; 187 if (B3) { 188 189 } 190 } while (counter > 0); 191 end = getTime(); 192 Log.d(TAG, "14:Time spent:" + (end - start) + "ms"); 193 194 Log.v(TAG, " - Demo end -"); 195 }
AnotherClass.java
1 public class AnotherClass { 2 public static boolean BOOL = true; 3 public static boolean BOOL2 = false; 4 public static final boolean BOOL3 = true; 5 public static final boolean BOOL4 = false; 6 public boolean bool; 7 }
實驗結果
共進行了五個不同環境下的測試實驗。
第一組:開機后在首頁
第二組:打開了很多應用以后
第三組:播放數字電視節目時啟動測試應用。
第四組:播放一段4K視頻時啟動測試應用。
第五組:在首頁啟動測試應用。
第六組:在首頁啟動測試應用。
單位:毫秒(ms)
序號 | 第一組 | 第二組 | 第三組 | 第四組 | 第五組 | 第六組 | 耗時均值 | |
1 | 347 | 344 | 348 | 346 | 344 | 344 | 345.5 | |
2 | 347 | 359 | 347 | 344 | 344 | 345 | 347.67 | |
3 | 346 | 348 | 346 | 345 | 344 | 344 | 345.5 | |
4 | 346 | 347 | 345 | 344 | 344 | 344 | 345 | |
5 | 347 | 346 | 346 | 344 | 344 | 345 | 345.17 | |
6 | 347 | 346 | 345 | 345 | 344 | 344 | 345.17 | |
7 | 346 | 346 | 346 | 344 | 344 | 344 | 345 | |
8 | 347 | 346 | 345 | 344 | 344 | 345 | 345.17 | |
9 | 2292 | 2277 | 2279 | 2268 | 2265 | 2264 | 2274.17 | |
10 | 1410 | 1411 | 1408 | 1411 | 1411 | 1411 | 1410.33 | |
11 | 345 | 345 | 344 | 345 | 344 | 344 | 344.5 | |
12 | 345 | 345 | 344 | 346 | 363 | 344 | 347.83 | |
13 | 346 | 345 | 350 | 345 | 345 | 345 | 346 | |
14 | 344 | 345 | 350 | 344 | 344 | 344 | 345.17 |
結論
- 對於if語句條件表達式的耗時應以條件結果為false的為准。
- 大多數情況下條件判斷所耗時間相當。
- 當條件被判斷為true時(對比3、4),即時后面的方法體是空的,也需要更多的時間來執行,對比9、10的結果更明顯。
- 非必須條件下不要在條件判斷語句處作運算(結果2),盡可能地將運算過程放在編譯時來執行。
- 變量是否被final修飾似乎對結果沒有什么影響(4、5與6、7),事實上這個結果讓我也很迷惑。不排除是我的測試環境與測試方法的問題。
- 變量定義在哪一個對象對結果沒有什么影響(結果6、結果8 )
- 對於另一個類對象中的靜態變量,所花費的時間相較於其它情況長很多(結果9、結果10)。盡量不要使用其它類對象中的非final靜態變量。
我相信沒什么應用的調試日志數量能達到1億條或者更多。即使是1410.33毫秒,分成1億份,它的時間也是微不足道的,並且市面上移動設備處理器通常都比我手里這塊要好。因此,實際結論是:你想怎樣用就怎樣用。當然,日志打印的耗時情況就不在我們的討論范圍之內了。