java - java中的运行时字节码更新和性能
问题描述
我有一些非常高性能的关键代码,在高层次上通过一些浮点比较或简单的谓词来做出一系列决定。代码可以写成决策树的形式。基本上每个节点都会进行谓词检查,然后决定要走哪条路径,直到我们到达某个叶节点。
为了提高性能而不是拥有这个决策树,我生成了一些在程序运行时编译的 if-else 代码块(基本上我为整个决策树生成代码,因为我事先知道谓词)。这确实大大提高了性能。现在我想做的下一个优化是在运行时修改代码,即在没有代码生成的旧世界中,有一个带有节点的决策树,我可以复制树并短路/跳过一些节点,从而压缩树并使整体计算速度更快。但是在生成的代码世界中,是否有任何工具可以通过根据计算期间可用的部分运行时数据修改我生成的 if-else 代码来实现相同的目标。还有什么是修改运行时代码的性能影响。
解决方案
首先,JVM 不允许您修改正在运行的代码。它允许您做的是在运行时生成新代码并加载它。
- 您可以通过生成源代码并编译它来做到这一点,就像您一直在做的那样。
- 您可以在字节码级别执行此操作;例如,使用 BCEL 之类的东西;见https://commons.apache.org/proper/commons-bcel/manual/bcel-api.html。
此外,还有一个 Oracle 赞助的项目 (GraalVM),在其中(如果我理解正确的话)您可以生成(松露)AST 并让框架负责代码生成。(目前似乎是实验性的,可能还没有准备好用于生产。)。
还有什么是修改运行时代码的性能影响。
那是 65,536 美元的问题!
一个含义是,每次修改代码(通过重新生成代码)时,都必须重新加载该方法,并且(对于传统的 JVM)再次经历解释和 JIT 编译阶段。以及可能依赖于修改后的代码的其他代码的去优化/重新优化。
那不会便宜。我猜测,每次执行此操作时,每种方法都会有数万或数十万条本机指令。
现在我想做的下一个优化是在运行时修改代码......
好的。所以我认为你实际上会更好地进行更复杂的代码生成。
而且,请记住,JIT 编译器将优化您生成的字节码,根据在解释方法时(在 JIT 编译之前)收集的统计信息执行分支预测等操作。
我还建议您在着手实施自己的优化器之前手动尝试一些优化并对其进行基准测试。
推荐阅读
- css - 假设我有一个最大宽度为 20 px 的列,我需要将内容包装在给定的宽度内
- python - 如何并行处理来自两个不同文件的行
- apache - 在 PCF 中以 Tomcat 为前端的 Apache
- jquery - mouseenter 和 mouseleave 下拉菜单问题
- ms-access - 为什么 SQLConfigDataSource 失败?
- java - SelectBox 的缩放文本
- r - 在 R 中使用带有 lapply/sapply 的匿名函数?
- javascript - 如何确定两个 ES6 类实例的相等性?
- r - boxCox() 不接受 map() 创建的线性模型,尽管是同一类?
- powershell-4.0 - 是否有可能对最终用户隐藏代码?