合肥国轩金通新材料产业基金成立
06-17
背景 Flink 提供了 Tuple0 ~ Tuple25 的 Tuple 类供用户选择。顾名思义,每个 Tuple 对象可以存储 0 ~ 25 个任意类型的字段,例如,图 1 显示了 Tuple2 的类定义。
由于腾讯云Oceanus流计算的客户业务场景比较复杂,需要使用更高维度的固定Tuple类,因此我们进一步扩展了Tuple类,包含Tuple甚至Tuple。图1:Tuple2的类定义,有两个f0和f1 但是,随着Tuple维数的增加,我们观察到一个奇怪的现象:虽然需要编译的源代码文件数量仅略有增加,但编译所需的时间却是越来越长,而且不是线性增长:原本只需一分钟就能完成的编译,现在往往需要一个多小时;如果在本机上编译,甚至可能需要几个小时才能完成。
这对我们的开发效率造成了一定的影响,所以有必要找出问题的根源。初步探索为了找出Tuple数量和编译时间之间的关系,我们还编写了一个自动化脚本,每次在源代码中添加一个更高维的Tuple类(例如放入Tuple26.java、Tuple27.java)等)。
观察项目的构建速度,画出如下曲线(图中的公式是利用Excel的趋势线拟合的),见下图2: 图2:Tuples总数与编译时间的关系。可以看出,编译时间随着Tuple数量的增加而增加。
变化曲线完美拟合三次函数,即算法的时间复杂度约为O(n^3)。时间复杂度这么高的根本原因必须找到,否则随着业务规模进一步扩大,编译时间会越来越难以接受。
为了解决这个问题,我们首先想到的就是利用Profiling工具对热点和通话时长进行统计分析。这里选择了JProfiler,它提供了许多有用的分析视图,可以快速找到问题的直接根源。
首先,我们开始编译缓慢的项目的编译和构建。默认情况下,它是基于Maven的,因此我们需要找出是否是Maven导致的问题。
我们使用的JDK版本是1.8.0_。图 3:使用采样模式对 Maven 编译过程进行采样。
首先,我们使用JProfiler的Sampling模式进行采样(图3)。其效果类似于连续运行jstack命令。
进行侵入式修改,使得到的数据更加准确;另一种Instrumentation模式适合发现问题热点后利用JVMTI动态修改字节码机制(在线定位神器btrace也是基于这个原理)进行本地详细分析。需要注意的是,默认情况下,采样不包括 JVM 内的调用。
由于我们需要定位JDK问题,所以需要清除Call tr??ee过滤器中的所有排除规则。否则,问题只能定位在Maven层。
程序运行一段时间后,我们发现了热点方法(见图4),即javac编译了内部List相关的调用;通过仔细跟踪调用链,我们发现 checkWithinBounds 方法太慢了。图4:寻找热点方法。
既然找到了热点方法,我们就需要探究一下这个方法在javac编译器中做了什么,为什么它的算法这么慢,是否有优化方法。详细定位 由于调用链中有Infer类,我们知道它是负责泛型类型推断的。
通过搜索slow genericcompilation等关键词,找到了JDK-bug表,JDK-here中也提到了同样的问题。然后我们跟踪 JDK- 和 JEP-。
在今年提出的 JEP 中,开发人员设计了一种新的 javac 方法类型检测机制 TA(Tiered Attribution)来取代现有的 SA(Speculative Attribution),可以大大加快多态表达式(Poly Expression)检查过程。通过阅读这个JEP(JDK增强提案)的描述,可以知道当前的SA算法需要对同一语法树上的多个不同目标进行多次类型检查。
例如,多态表达式有 N 个重载选项。 ,那么你需要检查N * 3 + 1次。
如果允许参数嵌套的话,就会将多个因子相乘在一起,这就会导致我们上面遇到的时间复杂度很高。这种新的 TA 算法为多态表达式提供了更高效的类型检查机制。
例如,省略重载决议过程中的类型检查,在重载决议之前,为每个方法调用过程中的多态参数表达式(poly argument expression)构建决议所需的自下而上的结构化类型,从而大大减少重载决策过程中的类型检查。减少尝试的总数。
根据这些错误单,JEP-已在 JDK 9 及更高版本上实现。因此我们转而使用当前发布的LTS版本JDK 11进行验证。
通过修改JAVA_HOME环境变量,Maven可以选择使用不同的JDK版本进行编译。修改JDK 11的路径后,我们重新编译并再次采样。
我们发现类型推断不再是消耗CPU最多的方法。 (图5):图5:编译到JDK 11时的热点方法。
同时,我们欣喜地发现整个项目只用了1.5分钟就构建完毕,相比之前的1个多小时有了质的飞跃(图6): 图6:新版本JDK的编译时间 可以看出,这个JEP立竿见影,将项目构建时间恢复到之前的情况。
版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
标签:
相关文章
06-17
06-18
06-17
06-17
06-18
06-08
06-06
最新文章
【玩转GPU】ControlNet初学者生存指南
【实战】获取小程序中用户的城市信息(附源码)
包雪雪简单介绍Vue.js:开学
Go进阶:使用Gin框架简单实现服务端渲染
线程池介绍及实际案例分享
JMeter 注释 18 - JMeter 常用配置组件介绍
基于Sentry的大数据权限解决方案
【云+社区年度征文集】GPE监控介绍及使用