這個文章的基礎是你基本已經完成了transfrom 的開發了,而後你碰到了編譯速度慢的問題。
在Transform的抽象類中有一個isIncremental方法,這個方法就表明着是否開啓增量編譯。
ide
編譯過程當中會去遍歷全部的jar .class文件,而後對文件進行io操做,以及asm插入代碼,這個過程耗時通常都會很長。
這裏須要注意一點:不是每次的編譯都是能夠怎量編譯的,畢竟一次clean build徹底沒有增量的基礎,因此,咱們須要檢查當前的編譯是否增量編譯。
須要作區分:
不是增量編譯,則清空output目錄,而後按照前面的方式,逐個class/jar處理
增量編譯,則要檢查每一個文件的Status,Status分爲四種,而且對四種文件的操做不盡相同
NOTCHANGED 當前文件不須要處理,甚至複製操做都不用
ADDED、CHANGED 正常處理,輸出給下一個任務
REMOVED 移除outputProvider獲取路徑對應的文件
上述是對增量的一些定義,能夠看出來在transfrom過程當中,應該是對文件打了一些tag標籤。
那麼咱們在開發階段首先要先區分當前此次是否是增量編譯,而後再編譯當前變動的文件,對變動的文件進行處理。
優化
我在代碼設計中,對transform進行了一次代碼抽象,把文件操做進行了一次抽象,同時把掃描以及.class文件操做進行了一些基礎封裝,後續的開發就能夠直接在這個的基礎上進行後續快速迭代開發。
ui
public void startTransform() {
try {
if (!isIncremental) {
outputProvider.deleteAll();
}
for (TransformInput input : inputs) {
for (JarInput jarInput : input.getJarInputs()) {
Status status = jarInput.getStatus();
String destName = jarInput.getFile().getName();
/* 重名名輸出文件,由於可能同名,會覆蓋*/
String hexName = DigestUtils.md5Hex(jarInput.getFile().getAbsolutePath()).substring(0, 8);
if (destName.endsWith(".jar")) {
destName = destName.substring(0, destName.length() - 4);
}
/*得到輸出文件*/
File dest = outputProvider.getContentLocation(destName + "_" + hexName,
jarInput.getContentTypes(), jarInput.getScopes(), Format.JAR);
if (isIncremental) {
switch (status) {
case NOTCHANGED:
break;
case ADDED:
foreachJar(dest, jarInput);
break;
case CHANGED:
diffJar(dest, jarInput);
break;
case REMOVED:
try {
deleteScan(dest);
if (dest.exists()) {
FileUtils.forceDelete(dest);
}
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
foreachJar(dest, jarInput);
}
}
for (DirectoryInput directoryInput : input.getDirectoryInputs()) {
foreachClass(directoryInput);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
複製代碼
我在遍歷循環jar,開始的時候咱們先判斷當前此次是否是增量編譯,若是不是增量則開始遍歷全部jar,若是是增量編譯,會去獲取當前jar的狀態,若是狀態是刪除則先掃描jar以後把output 中的文件刪除。若是狀態是ADD的狀況下,則掃描修改這個jar文件。最後若是是CHANGE狀態,則先掃描新久兩個jar,比較獲取刪除的文件,而後重複ADD操做。
spa
private void foreachClass(DirectoryInput directoryInput) throws IOException {
File dest = outputProvider.getContentLocation(directoryInput.getName(), directoryInput.getContentTypes(),
directoryInput.getScopes(), Format.DIRECTORY);
Map<File, Status> map = directoryInput.getChangedFiles();
File dir = directoryInput.getFile();
if (isIncremental) {
for (Map.Entry<File, Status> entry : map.entrySet()) {
Status status = entry.getValue();
File file = entry.getKey();
String destFilePath = file.getAbsolutePath().replace(dir.getAbsolutePath(), dest.getAbsolutePath());
File destFile = new File(destFilePath);
switch (status) {
case NOTCHANGED:
break;
case ADDED:
case CHANGED:
try {
FileUtils.touch(destFile);
} catch (Exception ignored) {
Files.createParentDirs(destFile);
}
modifySingleFile(dir, file, dest);
break;
case REMOVED:
Log.info(entry);
deleteDirectory(destFile, dest);
break;
}
}
} else {
changeFile(dir, dest);
}
}
複製代碼
這個是修改.class文件的操做 , 和修改jar包的邏輯基本同樣,可是又一個區別,若是是增量編譯的狀況下,咱們獲取的對象是一個Map,而非增量編譯的狀況下,咱們使用的是整個文件夾路徑。
設計
咱們的任務名DoubleTabTransform
這是一次全量編譯的耗時
3d