JDK8编译慢
slow JDK8 compilation
尝试在一个大项目上升级到 JDK8,与 JDK7 相比,JDK8 上的编译速度非常慢。
运行 详细模式下的编译器,JDK8 编译器在为从服务器到客户端的实体生成的大型转换器 class(映射)处停止。
在某些情况下,转换器方法会调用同一映射中的其他转换器方法 class.
解决方法是尝试将映射文件拆分为多个文件。这在仅编译映射 class 或它包含项目 (projectA) 时显着提高了性能。但是对于其他从 projectA 调用转换器方法的项目来说,编译时间非常慢。
另一种解决方法是使所有转换方法 return 为空,不调用任何其他方法。同样,projectA 的性能良好,但依赖项目的性能不佳。
ProjectA 使用泛型,但由于它与 JDK6 兼容,而 JDK6 没有引入通用类型推断,可能是另一个 JDK8 错误导致了这种速度下降。
所以可能断章取义,但对于通用类型推断,下面的一些线程建议升级到 JDK9。但由于它尚未发布,因此它不是升级的可行选择。
如果对 JDK8 进行修复的反向移植,那将是理想的。这是在以下 Whosebug 线程中请求的,但 Oracle 团队尚未回复。
Slow compilation with jOOQ 3.6+, plain SQL, and the javac compiler
我附上了 2 张关于堆在 JDK7 和 JDK8 中的外观的屏幕截图。这可能是导致 JDK8 变慢的原因吗?
谢谢!
更新20160314
Mapping class 中的转换器方法如下所示:
public static ResponseItemVO convert (ResponseItem pArg0){
if(pArg0==null){
return null;
}
ResponseItemVO ret = new ResponseItemVO();
ret.setErrorDetails(pArg0.getErrorDetails());
ret.setResult(Mapping.convert(pArg0.getResult()));
ret.setIdentifier(Mapping.convert(pArg0.getIdentifier()));
return ret;
}
VO 看起来像:
public class ResponseItemVO extends ResultVO<IdentifierVO, DetailsVO > {
public ResponseItemVO() {}
}
JDK7 堆:
JDK8 堆:
您已经注意到,there's a severe performance regression in Java 8 当谈到基于通用目标类型的重载解析时。您的情况的原因之一可能是编译器需要从赋值类型中找到合适的方法
ResultVO<Something, Something> result = Mapping.convert(...);
// heavy lookup here ---------------------------^^^^^^^
如果您控制代码生成器,并且不受向后兼容性的限制,可能值得考虑避免重载 convert()
方法。如果没有重载,编译器就不必在映射代码内部或调用站点执行重载解析工作。这肯定会快得多。
尝试1:通过在方法名中使用参数类型:
class Mapping {
public static ResponseItemVO convertResponseItem(ResponseItem pArg0){
if (pArg0==null){
return null;
}
ResponseItemVO ret = new ResponseItemVO();
ret.setErrorDetails(pArg0.getErrorDetails());
ret.setResult(Mapping.convertResult(pArg0.getResult()));
ret.setIdentifier(Mapping.convertIdentifier(pArg0.getIdentifier()));
return ret;
}
}
尝试 2:将 convert 方法移到别处,例如进入 VO
类型
class ResponseItemVO {
public static ResponseItemVO from(ResponseItem pArg0){
if (pArg0==null){
return null;
}
ResponseItemVO ret = new ResponseItemVO();
ret.setErrorDetails(pArg0.getErrorDetails());
ret.setResult(ResultVO.from(pArg0.getResult()));
ret.setIdentifier(IdentifierVO.from(pArg0.getIdentifier()));
return ret;
}
}
或更好...
class ResponseItem {
public ResponseItemVO toVO(){
ResponseItemVO ret = new ResponseItemVO();
ret.setErrorDetails(getErrorDetails());
ret.setResult(getResult().toVO());
ret.setIdentifier(getIdentifier().toVO());
return ret;
}
}
尝试在一个大项目上升级到 JDK8,与 JDK7 相比,JDK8 上的编译速度非常慢。
运行 详细模式下的编译器,JDK8 编译器在为从服务器到客户端的实体生成的大型转换器 class(映射)处停止。 在某些情况下,转换器方法会调用同一映射中的其他转换器方法 class.
解决方法是尝试将映射文件拆分为多个文件。这在仅编译映射 class 或它包含项目 (projectA) 时显着提高了性能。但是对于其他从 projectA 调用转换器方法的项目来说,编译时间非常慢。
另一种解决方法是使所有转换方法 return 为空,不调用任何其他方法。同样,projectA 的性能良好,但依赖项目的性能不佳。
ProjectA 使用泛型,但由于它与 JDK6 兼容,而 JDK6 没有引入通用类型推断,可能是另一个 JDK8 错误导致了这种速度下降。
所以可能断章取义,但对于通用类型推断,下面的一些线程建议升级到 JDK9。但由于它尚未发布,因此它不是升级的可行选择。 如果对 JDK8 进行修复的反向移植,那将是理想的。这是在以下 Whosebug 线程中请求的,但 Oracle 团队尚未回复。
Slow compilation with jOOQ 3.6+, plain SQL, and the javac compiler
我附上了 2 张关于堆在 JDK7 和 JDK8 中的外观的屏幕截图。这可能是导致 JDK8 变慢的原因吗?
谢谢!
更新20160314
Mapping class 中的转换器方法如下所示:
public static ResponseItemVO convert (ResponseItem pArg0){
if(pArg0==null){
return null;
}
ResponseItemVO ret = new ResponseItemVO();
ret.setErrorDetails(pArg0.getErrorDetails());
ret.setResult(Mapping.convert(pArg0.getResult()));
ret.setIdentifier(Mapping.convert(pArg0.getIdentifier()));
return ret;
}
VO 看起来像:
public class ResponseItemVO extends ResultVO<IdentifierVO, DetailsVO > {
public ResponseItemVO() {}
}
JDK7 堆:
您已经注意到,there's a severe performance regression in Java 8 当谈到基于通用目标类型的重载解析时。您的情况的原因之一可能是编译器需要从赋值类型中找到合适的方法
ResultVO<Something, Something> result = Mapping.convert(...);
// heavy lookup here ---------------------------^^^^^^^
如果您控制代码生成器,并且不受向后兼容性的限制,可能值得考虑避免重载 convert()
方法。如果没有重载,编译器就不必在映射代码内部或调用站点执行重载解析工作。这肯定会快得多。
尝试1:通过在方法名中使用参数类型:
class Mapping {
public static ResponseItemVO convertResponseItem(ResponseItem pArg0){
if (pArg0==null){
return null;
}
ResponseItemVO ret = new ResponseItemVO();
ret.setErrorDetails(pArg0.getErrorDetails());
ret.setResult(Mapping.convertResult(pArg0.getResult()));
ret.setIdentifier(Mapping.convertIdentifier(pArg0.getIdentifier()));
return ret;
}
}
尝试 2:将 convert 方法移到别处,例如进入 VO
类型
class ResponseItemVO {
public static ResponseItemVO from(ResponseItem pArg0){
if (pArg0==null){
return null;
}
ResponseItemVO ret = new ResponseItemVO();
ret.setErrorDetails(pArg0.getErrorDetails());
ret.setResult(ResultVO.from(pArg0.getResult()));
ret.setIdentifier(IdentifierVO.from(pArg0.getIdentifier()));
return ret;
}
}
或更好...
class ResponseItem {
public ResponseItemVO toVO(){
ResponseItemVO ret = new ResponseItemVO();
ret.setErrorDetails(getErrorDetails());
ret.setResult(getResult().toVO());
ret.setIdentifier(getIdentifier().toVO());
return ret;
}
}