JVM何时考虑用于字节码优化的代码?

时间:2017-05-05 21:16:04

标签: java performance bytecode jvm-hotspot

我正在尝试了解JVM和HotSpot优化器内部。

我解决了尽可能快地使用大量节点初始化对象树结构的问题。 现在,对于给定的每个树结构,我们生成Java源代码以初始化树,如下所示。最后,我们有数千个这样的课程。

public class TypeATreeNodeInitializer {

    public TypeATreeNode initialize(){
        return getTypeATree();

    }

    private TypeATreeNode getTypeATree() {
        TypeATreeNode node = StaticTypeAFactory.create();

        TypeBTreeNode child1 = getTypeBTreeNode1(); 
        node.getChildren().add(child1);

        TypeBTreeNode child2 = getTypeBTreeNode2(); 
        node.getChildren().add(child2);

        //... may be many more children

        return node;
    }

    private TypeBTreeNode getTypeBTreeNode1() {
        TypeBTreeNode node = StaticTypeBFactory.create();

        TypeBTreeNode child1 = getTypeCTreeNode1(); 
        node.getChildren().add(child1);

        //store of value in variable first
        String value1 = "Some value";
        // assign value to node
        node.setSomeValue(value1);

        boolean value2 = false;
        node.setSomeBooleanValue(value2);


        return node;
    }



    private TypeBTreeNode getTypeCTreeNode1() {
        // ...
        return null;
    }

    private TypeBTreeNode getTypeBTreeNode2() {
        // ...
        return null;
    }

    //...  many more child node getter / initializer
}

如您所见,要分配给树节点的值首先存储在局部变量中。查看生成的字节代码,结果如下:

  1. 从常量池到堆栈的变量加载//例如字符串“Some Value”

  2. 变量存储在局部变量

  3. 从方法目标到堆栈的负载//例如TypeBTreeNode

  4. 从局部变量加载变量//“Some Value”

  5. 调用setter

  6. 然而,这可以通过不存储到局部变量并直接传递参数来缩短。所以,它变成了:

    1. 将方法目标推送到堆栈上//例如TypeBTreeNode

    2. 然后将常量加载到堆栈//“Some Value”

    3. 然后调用setter

    4. 我知道在其他语言(例如C ++)中,编译能够进行这样的优化。

      在Java中,HotSpot优化器在运行时负责这种魔术 但是,据我所知,HotSpot只在500ths方法调用(客户端VM)之后启动。

      问题:

      • 我是否理解正确:如果我只对每个树初始化一次,但是对于生成的TreeInitializers的大量数据(假设为10.000),则为每个TreeInitializer执行第一个字节代码序列,因为它们是不同的类使用不同的方法,每个方法只调用一次?

      • 我怀疑使用没有本地人的重写速度很快,因为我节省了大约三分之一的字节码指令和可能的昂贵的变量。我知道没有测量就很难说,但改变发生器代码是非常重要的,所以你认为值得一试吗?

1 个答案:

答案 0 :(得分:1)

删除像这样的临时/堆栈变量几乎总是过早优化。您的处理器每秒可处理数亿条指令;同时,如果您正在初始化成千上万的任何,那么您的程序可能会在等待内存分配时阻塞。

我的建议始终是推迟优化,直到您对代码进行了分析。在此期间,编写代码尽可能易于阅读,这样当您需要返回并修改某些内容时,很容易找到需要更新的地方。