java中的运行时字节码更新与性能

java中的运行时字节码更新与性能,java,performance,jvm,runtime,code-generation,Java,Performance,Jvm,Runtime,Code Generation,我有一些非常高性能的关键代码,在高级别上,它通过进行一些浮点比较或简单谓词来做出一系列决策。 代码可以以决策树的形式编写。基本上,每个节点都会执行谓词检查,然后决定采用哪条路径,直到到达某个叶节点 为了提高性能而不是拥有这个决策树,我生成了一些if-else代码块,这些代码块在程序运行时被编译(基本上我为整个决策树生成代码,因为我事先知道谓词)。这确实大大提高了性能。 现在我想做的下一个优化是在运行时修改代码,也就是说,在没有代码生成的旧世界中,有一个带有节点的决策树,我可以复制树并短路/跳过一

我有一些非常高性能的关键代码,在高级别上,它通过进行一些浮点比较或简单谓词来做出一系列决策。 代码可以以决策树的形式编写。基本上,每个节点都会执行谓词检查,然后决定采用哪条路径,直到到达某个叶节点

为了提高性能而不是拥有这个决策树,我生成了一些if-else代码块,这些代码块在程序运行时被编译(基本上我为整个决策树生成代码,因为我事先知道谓词)。这确实大大提高了性能。
现在我想做的下一个优化是在运行时修改代码,也就是说,在没有代码生成的旧世界中,有一个带有节点的决策树,我可以复制树并短路/跳过一些节点,从而压缩树并提高整体计算速度。但是在生成的代码世界中,有没有工具可以通过基于计算期间可用的部分运行时数据修改生成的if-else代码来实现同样的效果。另外,修改运行时代码对性能的影响是什么

首先,JVM不允许您修改正在运行的代码。它允许您在运行时生成新代码并加载

  • 您可以通过生成源代码并编译它来实现这一点,就像您一直在做的那样
  • 您可以在字节码级别执行此操作;e、 g.使用类似BCEL的东西;看
此外,还有一个Oracle赞助的项目(GraalVM)(如果我理解正确的话),您可以在其中生成(块菌)AST,并让框架负责代码生成。(目前它似乎处于试验阶段,可能还没有准备好投入生产使用。)


另外,修改运行时代码对性能的影响是什么

这就是65536美元的问题

其中一个含义是,每次修改代码(通过重新生成代码)时,必须重新加载该方法,并且(对于传统JVM)再次经历解释和JIT编译阶段。以及依赖于修改后的代码的其他代码的潜在去优化/再优化

那可不便宜。我猜每次你这样做的时候,每个方法都会有几万或几十万条本机指令


现在我要做的下一个优化是在运行时修改代码

嗯。因此,我认为您实际上最好进行更复杂的代码生成

但也要记住,JIT编译器将优化生成的字节码,根据解释方法时(JIT编译之前)收集的统计数据进行分支预测

我还建议您在着手实施自己的优化器之前,手动尝试一些优化并对它们进行基准测试。

这就是我使用我的

e、 g

我建议使用一个不改变的已知接口,您可以调用并让生成的代码实现该接口


这不支持重新加载类,但您可以每次生成一个新的类名或每次使用不同的类加载器。

您是否想过改用规则引擎?(如drools)这是否用于提供非常高qps的亚毫秒(几微秒)应用服务器?字符串解析和生成类对我来说效率有点低:/I我需要生成代码或根据判断修改代码,否则通常需要10-15分钟sec@user179156这在低延迟交易应用程序中使用,需要11美元线对线。字符串生成效率很低,第一个类需要500毫秒才能编译,但是加载该类后没有任何影响。@user179156一旦预热,生成的代码预计需要1 us或更少的时间。谢谢澄清。在我的用例中,我需要对数千个项目做出决策,每个决策都需要在10微秒或更短的时间内进行计算。我需要为每个请求生成决策树代码,所以对每个请求产生500毫秒的影响对我来说是不可能的。您是否建议其他更高效的方法,是否有直接生成编译代码的方法?
// dynamically you can call
String className = "mypackage.MyClass";
String javaCode = "package mypackage;\n" +
                 "public class MyClass implements Runnable {\n" +
                 "    public void run() {\n" +
                 "        System.out.println(\"Hello World\");\n" +
                 "    }\n" +
                 "}\n";
Class aClass = CompilerUtils.CACHED_COMPILER.loadFromJava(className, javaCode);
Runnable runner = (Runnable) aClass.newInstance();
runner.run();