使用JavaC1.8的字符串连接性能优于Eclipse编译器?

使用JavaC1.8的字符串连接性能优于Eclipse编译器?,java,eclipse,string,Java,Eclipse,String,我是Java新手 起初,我在不同的情况下测试String和StringBuilder的性能 然而,我发现由javac和eclipse编译的相同代码执行的方式不同 我了解到,String串联实际上使用的是StringBuilder,但为什么在这种情况下,String比StringBuilder快1.5倍,性能却有如此大的差异呢 以下是我的测试代码: public class StringTest { public StringTest() { boolean flag =

我是Java新手

起初,我在不同的情况下测试
String
StringBuilder
的性能

然而,我发现由
javac
eclipse
编译的相同代码执行的方式不同

我了解到,
String
串联实际上使用的是
StringBuilder
,但为什么在这种情况下,String比
StringBuilder
快1.5倍,性能却有如此大的差异呢

以下是我的测试代码:

public class StringTest {
    public StringTest() {
        boolean flag = true;
        int code = 10001, type = 1;

        long time = System.nanoTime();
        for (int i = 0; i < 10000000; ++i) {
            String msg = Long.toString(i * 1000000000);
            stringHandler(code, type, flag, msg);
        }
        System.out.println("Took " + (System.nanoTime() - time) + " ns by String");

        time = System.nanoTime();
        for (int i = 0; i < 10000000; ++i) {
            String msg = Long.toString(i * 1000000000);
            stringBuilderHandler(code, type, flag, msg);
        }
        System.out.println("Took " + (System.nanoTime() - time) + " ns by StringBuilder");
    }

    public String stringBuilderHandler(int code, int type, boolean flag, String msg) {
        StringBuilder sb = new StringBuilder();

        sb.append("{\"bool\":").append(flag).append(",")
                .append("\"code\":").append(code).append(",")
                .append("\"type\":").append(type).append(msg).append("}");

        return sb.toString();
    }

    public String stringHandler(int code, int type, boolean flag, String msg) {
        String str = "{\"bool\":";
        str += flag;
        str += ",";
        str += "\"code\":";
        str += code;
        str += ",";
        str +=  "\"type\":";
        str += type;
        str += msg;
        str += "}";
        return str;
    }

    public static void main(String[] args) {
        StringTest st = new StringTest();
    }
}
使用Eclipse:

Took 4282720864 ns by String
Took 1709934263 ns by StringBuilder


您的
stringBuilderHandler
中存在一个巨大的问题,这就是您在每次调用时都要创建一个
StringBuilder
的新实例,此时您应该重用同一实例以查看连接。在
stringHandler
中执行类似操作:重用相同的
String
变量,然后您将注意到差异。此外,您应该遵循此处所示的适当微基准的规则:或者使用卡钳或JMH之类的微基准框架。

您的
stringBuilderHandler
中存在一个巨大的问题,这就是您在每次调用时都要创建一个
StringBuilder
的新实例,当您应该重用同一实例以查看连接时。在
stringHandler
中执行类似操作:重用相同的
String
变量,然后您将注意到差异。此外,您应该遵循此处所示的适当微基准的规则:或者使用卡钳或JMH等微基准框架。

您可以使用
javap-c
反编译代码,并查看字节码在这两种情况下的外观。@Jesper感谢您的建议。我注意到eclipse编译的字节码调用了String.valueOf,而javac没有调用。但正如我所说的,我是Java新手,我真的不明白这对性能有多重要。如果您能给我进一步的解释,我将非常感激。您是否使用相同的JVM来执行代码?哪个JVM?@bayou.io是的,它是一样的,jre1.8.0_45,我的操作系统中只有这个环境。如果oracle的JVM为oracle的javac输出进行了更好的优化,这并不奇怪——不是出于邪恶的原因。jvm需要查看指令模式,猜测它的作用,并假设一个可能是最优的策略。您可以使用
javap-c
反编译代码,并查看字节码在这两种情况下的样子。@Jesper感谢您的建议。我注意到eclipse编译的字节码调用了String.valueOf,而javac没有调用。但正如我所说的,我是Java新手,我真的不明白这对性能有多重要。如果您能给我进一步的解释,我将非常感激。您是否使用相同的JVM来执行代码?哪个JVM?@bayou.io是的,它是一样的,jre1.8.0_45,我的操作系统中只有这个环境。如果oracle的JVM为oracle的javac输出进行了更好的优化,这并不奇怪——不是出于邪恶的原因。jvm需要查看指令模式,猜测它的作用,并假设一个可能是最优的策略。是的,我知道这个问题,但我需要在方法内部创建实例,因为我正在实现一个处理程序,该处理程序将由不同的线程调用,我的同事提到了在方法外部声明的StringBuffer的糟糕性能。正如我所说,我是Java新手,所以我真的不知道如何使用这些框架,但我想尝试一下。这两个不同的行为让我很困惑。你需要解决的用例是什么?看起来更像是需要添加内容,然后将其打印到文件或其他文件中。我会使用
BlockingQueue
而不是其他同步技术,最后使用
StringBuilder
清空队列并连接其内容一次。或者你只需要一个记录设备。@Luiggi Mendoza谢谢你的回复。事实上,我正在通过网络进行json传输,我使用Netty作为我的网络框架。我仍然不知道在哪里需要同步字符串操作。这应该被设计成原子性的。我猜你把问题混在一起了。我建议您发布一个新问题,解释您当前的用例,表达您的具体设计问题,并在那里寻求解决该问题的指导。这个问题是关于字符串连接的,这也是这个答案的范围。给定的代码只是为了测试当我需要在方法中附加字符串时,我应该选择使用哪一个。也许这是网络应用中的错误设计?但我最大的困惑是eclipse和javac之间的不同行为,这让我想更改我的IDE,因为我发现NetBeans没有这样的问题。是的,我知道这个问题,但我需要在方法内部创建实例,因为我正在实现一个处理程序,该处理程序将由不同的线程调用,我的同事提到了在方法外部声明的StringBuffer的糟糕性能。正如我所说,我是Java新手,所以我真的不知道如何使用这些框架,但我想尝试一下。这两个不同的行为让我很困惑。你需要解决的用例是什么?看起来更像是需要添加内容,然后将其打印到文件或其他文件中。我会使用
BlockingQueue
而不是其他同步技术,最后使用
StringBuilder
清空队列并连接其内容一次。或者你只需要一个记录设备。@Luiggi Mendoza谢谢你的回复。事实上,我正在通过网络进行json传输,我使用Netty作为我的网络框架。我仍然不知道在哪里需要同步字符串操作。这应该被设计成原子性的。我猜你把问题混在一起了。我建议您发布一个新问题,解释您当前的用例,表达您的具体需求
Took 4282720864 ns by String
Took 1709934263 ns by StringBuilder