Java動態編譯優化——提升編譯速度(N倍)
一、前言
最近一直在研究Java8 的動態編譯, 並且也被ZipFileIndex$Entry 記憶體洩漏所困擾,在無意中,看到一個第三方外掛的動態編譯。並且編譯速度是原來的2-3倍。原本打算直接用這個外掛,但是發現外掛的編譯原始碼存在我之前已經解決過的記憶體洩漏問題。所以拿其原始碼,進行改善。
二、第三方外掛
1、maven配置
我找到的這個第三方編譯外掛有兩個,第一個是:Talismane Utilities ,在maven倉庫中可搜到相關pom的配置:
http://mvnrepository.com/search?q=Talismane+Utilities
這個外掛也能編譯,但是編譯速度和記憶體洩漏問題依然存在(廢棄)
第二個外掛是Java Runtime Compiler , 可在Maven倉庫中找到 : http://mvnrepository.com/artifact/net.openhft/compiler
我使用的版本是最新的2.3.1 , 進行反編譯後:
2、外掛原始碼更改
拿到Java Runtime Compiler外掛的原始碼後,能找到有個CachedCompiler類,我對其compilerFromJava方法進行了更改,加上了編譯options引數。具體程式碼如下:
Map<String, byte[]> compileFromJava(@NotNull String className, @NotNull String javaCode, @NotNull final PrintWriter writer, MyJavaFileManager fileManager) {
Object compilationUnits;
if(this.sourceDir != null) {
String filename = className.replaceAll("\\.", '\\' + File.separator) + ".java";
File file = new File(this.sourceDir, filename);
CompilerUtils.writeText(file, javaCode);
compilationUnits = CompilerUtils.s_standardJavaFileManager.getJavaFileObjects(new File[]{file});
} else {
this.javaFileObjects.put(className, new JavaSourceFromString(className, javaCode));
compilationUnits = this.javaFileObjects.values();
}
System.setProperty("useJavaUtilZip", "true");
List<String> options = new ArrayList<>();
options.add("-encoding");
options.add("UTF-8");
options.add("-classpath");
//獲取系統構建路徑
options.add(buildClassPath());
//不使用SharedNameTable (jdk1.7自帶的軟引用,會影響GC的回收,jdk1.9已經解決)
options.add("-XDuseUnsharedTable");
options.add("-XDuseJavaUtilZip");
boolean ok = CompilerUtils.s_compiler.getTask(writer, fileManager, new DiagnosticListener<JavaFileObject>() {
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
if(diagnostic.getKind() == Kind.ERROR) {
writer.println(diagnostic);
}
}
}, options, (Iterable)null, (Iterable)compilationUnits).call().booleanValue();
Map<String, byte[]> result = fileManager.getAllBuffers();
if(!ok) {
if(this.sourceDir == null) {
this.javaFileObjects.remove(className);
}
return Collections.emptyMap();
} else {
return result;
}
}
3、具體編譯時測試類
利用原來的測試類,以10萬個編譯測試為例,進行測試,編譯速度提升N倍,同時記憶體溢位問題也僅存在ZipFIleIndex
package com.yunerp.web.util.run.compile;
import com.yunerp.web.util.run.WebInterface;
import com.yunerp.web.util.run.dynamic.compiler.CompilerUtils;
import java.util.HashMap;
import java.util.Map;
public class DynaCompTest{
public static Map<String,Object> map = new HashMap<>();
public static void main(String[] args) throws Exception {
String code = "import java.util.HashMap;\n" +
"import com.yunerp.web.vaadin.message.alert;\n" +
"import java.util.List;\n" +
"import java.util.ArrayList;\n" +
"import com.yunerp.web.vaadin.util.modularfuntion.base.BaseUtil;\n" +
"import com.yunerp.web.vaadin.util.function.TableFuntionUtil;\n" +
"import com.yunerp.web.vaadin.util.modularfuntion.stoUtil.StoUtil;\n" +
"import java.util.Map;import com.yunerp.web.vaadin.util.modularfuntion.user.mini.HomePageUtil;\n" +
"import com.yunerp.web.util.run.WebInterface;\n" +
"\n" +
"public class web2905763164651825363 implements WebInterface {\n" +
" public Object execute(Map<String,Object> param) {\n" +
" System.out.println(param.get(\"key\")+ \"次測試編譯\");" +
" return null;\n" +
" }\n" +
"}";
String name = "web2905763164651825363";
for(int i=0;i<100000;i++){
long time1 = System.currentTimeMillis();
DynamicEngine de = new DynamicEngine();
try {
// Class cl = de.javaCodeToObject(name,code);
Class cl = CompilerUtils.CACHED_COMPILER.loadFromJava(name, code);
if (cl==null){
System.out.println("編譯失敗/類載入失敗");
continue;
}
WebInterface webInterface = (WebInterface)cl.newInstance();
Map<String,Object> param = new HashMap<>();
param.put("key",i);
webInterface.execute(param);
}catch (Exception e) {
e.printStackTrace();
}
long time2 = System.currentTimeMillis();
System.out.println("次數:"+i+" time:"+(time2-time1));
}
}
}
4、編譯速度對比
之前的編譯程式碼編譯速度:
使用更改後的第三方編譯程式碼編譯速度如下:
注: 因為之前的就存在ZipFileIndex問題,更改後的編譯原始碼也只是提升編譯速度,ZipFileIndex記憶體洩漏的問題仍然存在,目前唯一的解決方案是升級Java8 到 Java10
相關文章
- webpack編譯速度提升之DllPluginWeb編譯Plugin
- N1064編譯鏈編譯編譯
- Java動態編譯和熱更新Java編譯
- JIT-動態編譯與AOT-靜態編譯:java/ java/ JavaScript/Dart亂談編譯JavaScriptDart
- JVM編譯優化JVM編譯優化
- Android 編譯優化Android編譯優化
- 優化使用kotlin開發Android app的編譯速度優化KotlinAndroidAPP編譯
- 深入理解Java的動態編譯Java編譯
- Java編譯與反編譯Java編譯
- ☕【Java技術指南】「編譯器專題」深入分析探究“靜態編譯器”(JAVA\IDEA\ECJ編譯器)是否可以實現程式碼優化?Java編譯Idea優化
- [譯] 優化 Swift 的編譯時間優化Swift編譯
- Java動態編譯優化——URLClassLoader 記憶體洩漏問題解決Java編譯優化記憶體
- 編譯lua動態庫編譯
- vue3編譯最佳化之“靜態提升”Vue編譯
- Java動態編譯優化——ZipFileIndex記憶體洩漏問題分析解決Java編譯優化Index記憶體
- C++編譯器優化C++編譯優化
- 優化 Xcode 編譯時間優化XCode編譯
- 後端編譯與優化後端編譯優化
- 有關Linux的可執行程式——動態編譯、靜態編譯、readelfLinux行程編譯
- 用實驗的思路優化webpack4專案編譯速度優化Web編譯
- go的編譯優化問題Go編譯優化
- 編譯器優化:方法內聯編譯優化
- Taro編譯打包優化實踐編譯優化
- 使用 ccache 增加 Xcode 編譯速度XCode編譯
- 如何提高 Xcode 的編譯速度XCode編譯
- 狂攬兩千星,速度百倍提升,高效能Python編譯器Codon開源Python編譯
- Dubbo原始碼之動態編譯原始碼編譯
- iOS自動化編譯打包iOS編譯
- Ruby 將引入新 JIT 編譯器:YJIT,平均速度提升 23%編譯
- 前端工程中的編譯時優化前端編譯優化
- [譯] 提高 10 倍效能:優化靜態網站優化網站
- dll預編譯提高webpack打包速度編譯Web
- mingw下編譯zlib quazip動態庫編譯
- java反編譯工具Java編譯
- 在 docker-in-docker 環境中使用 cache-from 提升編譯速度Docker編譯
- Java程式碼的編譯與反編譯那些事兒Java編譯
- 騰訊視訊編譯優化記錄編譯優化
- Linux 下如何繞過編譯器優化Linux編譯優化