Ⅰ Xcode 構建速度優化(一)衡量編譯時間
隨著項目不斷迭代,工程文件越來越多,引用的三方庫也越來越多,這些直接導致編譯時間的不斷增加,完整編譯一次項目動輒需要五分鍾以上時間,實在有些影響開發效率,是時候來一波提速了。
為編譯和構建提速,首先我們需要對速度有一個衡量標准:准確獲得構建用時
首先,我們需要定義要衡量和優化的內容。 有兩種選擇:
xcode默認情況下會跟蹤所有構建,我們可以通過更改xcode相關設置,來在活動查看器中顯示出構建時間,通過命令行:
每次編譯成功後,會在Successed之後顯示出所用時間:
Xcode Build Timing Summary是Xcode10中加入的用於查看獲取構建時間和發現用時瓶頸方面的最有利工具。 可以通過Proct->Perform Action->Build With Timing Summary來開啟:這樣在 Build Log 的末尾就會添加 Timing Summary Log。我們可以通過這個 log 看到哪個階段是耗時的,便於我們進行優化。
如上圖中: xib階段的編譯耗時明顯是比普通c文件要多的,意味著我們可以通過減少xib方式來優化提升速度
而c文件的編譯用時比總時間還要長,是因為c文件是並行編譯的
在命令行中同樣可以開啟這個功能:
常用的第三方工具有 BuildTimeAnalyzer 、 xcode-build-times-rendering 、 XCLogParser 。
BuildTimeAnalyzer可以統計可以得出某個文件的類型檢查時長,每個表達式的類型檢查時長。
xcode-build-times-rendering是一個Ruby編寫的第三方工具,可以方便地分別測量目標的構建時間並在圖表上顯示它們,使用gem安裝
接下來使用這個工具自帶命令配置項目
然後構建項目並生成報告:
這個工具使用上比較簡單,缺點是只能從宏觀上生成各個target編譯的整體圖標,無法詳細列出各個內部編譯明細
XCLogParser可以詳細列出各個Target和內部每個文件的編譯耗時,對我們分析編譯時間瓶頸非常有幫助,它的工作原理主要是做為解析器,通過解析xcode編譯生成的xcactivitylog日誌來記錄
安裝:
編譯項目後,進行安裝
安裝成功後通過命令:
會自動在當前目錄的 build/xclogparser/reports/ 路徑下生成報告,其中--project參數需要設置為待分析項目的名字,並注意當前在終端切換到希望寫入日誌的目錄。
報告截圖:
這個工具將作為我們後面分析提升編譯構建速度的主要使用工具。
經過我多次在不同時間段,不同電腦上不斷嘗試編譯,
我發現編譯耗時是一個比較玄的東西,及時在同一台電腦,同一個項目, 同一套環境配置下,編譯用時也會隨著電腦當前狀態(包括同時打開進程、散熱等等)上下大幅跳動,就像演算法時間復雜度一樣,有時候我們明明做了一些細微的優化,但是結果反而是編譯耗時增加了,這是很正常的事情
所以,衡量這個標准需要我們取多次試驗中的平均值作為參考。
Ⅱ 一個超大數(比如10的20次方),求它的約數個數,要求用最快的方法,編譯運行時間不超過一秒!!
重寫寫了個java演算法,效率很理想。
不過long只能支持到10的18次方
運行環境:E8400 + 4G RAM + JDK 1.5 + XP SP3(公司的機子就是牛啊!!!!)
import java.util.ArrayList;
import java.util.List;
public class Submultiple {
public static void main(String args[]){
long start = System.currentTimeMillis();
int[] primeNumAry = new int[64];
get64PrimeNumber(primeNumAry);
long num = 1000000000000000000L;
long orgNum = num;
int facCount = 0;
List<Integer> list = new ArrayList<Integer>();
for(int index = 0, factor = primeNumAry[index]; num != 1; ){
if(num % factor == 0){
facCount++;
num = num /factor;
if(num == 1){
list.add(facCount);
}
continue;
}else{
list.add(facCount);
factor = primeNumAry[++index];
facCount = 0;
}
}
long totalCount = 1L;
for(int item: list){
totalCount *= (item + 1);
}
long end = System.currentTimeMillis();
System.out.println("For number " + orgNum + ", Total " + (end - start)
+ " million seconds for " + totalCount + " submultiples");
}
private static void get64PrimeNumber(int[] primeNumAry) {
Label1: for(int i = 2, count = 0; count < 64; i++){
for(int j = 2; j < i; j++){
if(i % j == 0){
continue Label1;
}
}
primeNumAry[count++] = i;
}
}
}
--------------
For number 1000000000000000000, Total 0 million seconds for 361 submultiples