Java toString的性能优化方案比较

Java toString的性能优化方案比较

通常toString重写会优先使用StringBuffer来进行append,但jdk1.7以上,已经做了充分优化,让我们通过实际测试数据,来对比下是否String的concat(+)是否真的会差呢?

测试环境,JUnit和JMH(JMH相关资料请自行百度),相关Maven依赖如下:

        <!-- 测试部分-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
                <dependency>
            <groupId>org.openjdk.jmh</groupId>
            <artifactId>jmh-generator-annprocess</artifactId>
            <version>1.12</version>
            <scope>provided</scope>
        </dependency>

首先基于通用的System的当前时间进行测试,测试代码如下:

public String toStringConcat() {
        return "ToStringTest{" +
                "att1='" + att1 + '\'' +
                ", att2='" + att2 + '\'' +
                ", att3='" + att3 + '\'' +
                '}';
    }

    public String toStringSb() {
        final StringBuffer sb = new StringBuffer("ToStringTest{");
        sb.append("att1='").append(att1).append('\'');
        sb.append(", att2='").append(att2).append('\'');
        sb.append(", att3='").append(att3).append('\'');
        sb.append('}');
        return sb.toString();
    }

    public String toStringStringBuilder() {
        final StringBuilder sb = new StringBuilder("ToStringTest{");
        sb.append("att1='").append(att1).append('\'');
        sb.append(", att2='").append(att2).append('\'');
        sb.append(", att3='").append(att3).append('\'');
        sb.append('}');
        return sb.toString();
    }

下面通过JUnit进行允许测试

/**
     * 功能说明 :junit测试try性能
     * @author  Zain 2016/7/14  10:28
     * @return  result
     * @params
     */
    @Test
    public void simpleTest() throws Exception {
        System.out.println("toStringConcat ---------------------------------");
        long startTime = System.currentTimeMillis();
        try {
            for (int i = 0; i < 1000000; i++) {
                toStringConcat();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("toStringConcat " + (endTime - startTime) + " milliseconds");

        System.out.println("toStringSb ---------------------------------");
        startTime = System.currentTimeMillis();
        try {
            for (int i = 0; i < 1000000; i++) {
                toStringSb();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        endTime = System.currentTimeMillis();
        System.out.println("toStringSb " + (endTime - startTime) + " milliseconds");


        System.out.println("toStringStringBuilder ---------------------------------");
        startTime = System.currentTimeMillis();
        try {
            for (int i = 0; i < 1000000; i++) {
                toStringStringBuilder();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        endTime = System.currentTimeMillis();
        System.out.println("toStringStringBuilder " + (endTime - startTime) + " milliseconds");


    }
代码很简单,直接给测试结果:
toStringConcat ---------------------------------
toStringConcat 80 milliseconds
toStringSb ---------------------------------
toStringSb 374 milliseconds
toStringStringBuilder ---------------------------------
toStringStringBuilder 146 milliseconds
当然,每次运行结果可能不一样,由于JVM“热身”的原因,我们调整下运行顺序,将String的concat放到最后,运行结果如下:
toStringSb ---------------------------------
toStringSb 370 milliseconds
toStringStringBuilder ---------------------------------
toStringStringBuilder 235 milliseconds
toStringConcat ---------------------------------
toStringConcat 69 milliseconds
这里已经可以看到曾经邪恶的+,貌似更加高效,下面用JMH测试进一步有效验证。
测试代码如下:
   @Benchmark
    @BenchmarkMode(Mode.Throughput)
    @OutputTimeUnit(TimeUnit.MILLISECONDS)
    public void toStringConcatBenchmark() {
        int j = 3;
        try {
            for (int i = 0; i < 1000000; i++) {
                toStringConcat();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    @OutputTimeUnit(TimeUnit.MILLISECONDS)
    public void toStringSbBenchmark() {
        int j = 3;
        for (int i = 0; i < 1000000; i++) {
            try {
                toStringSb();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Benchmark
    @BenchmarkMode(Mode.Throughput)
    @OutputTimeUnit(TimeUnit.MILLISECONDS)
    public void toStringStringBuilderBenchmark() {
        int j = 3;
        for (int i = 0; i < 1000000; i++) {
            try {
                toStringStringBuilder();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
JMH允许代码:
    /**
     * 功能说明 :JMH测试try性能
     * @author  Zain 2016/7/14  10:29
     * @return  result
     * @params
     */
    @Test
    public void benchmarkTest() throws Exception {
        Options opt = new OptionsBuilder()
                .include(ToStringTest.class.getSimpleName())
                .forks(1)
                .build();
        new Runner(opt).run();
    }
运行结果:
# Run complete. Total time: 00:02:10
第一次
Benchmark                                     Mode  Cnt  Score    Error   Units
ToStringTest.toStringConcatBenchmark         thrpt   20  0.029 ±  0.001  ops/ms
ToStringTest.toStringSbBenchmark             thrpt   20  0.006 ±  0.001  ops/ms
ToStringTest.toStringStringBuilderBenchmark  thrpt   20  0.008 ±  0.001  ops/ms

第二次
Benchmark                                     Mode  Cnt  Score    Error   Units
ToStringTest.toStringConcatBenchmark         thrpt   20  0.029 ±  0.001  ops/ms
ToStringTest.toStringSbBenchmark             thrpt   20  0.006 ±  0.001  ops/ms
ToStringTest.toStringStringBuilderBenchmark  thrpt   20  0.007 ±  0.001  ops/ms
综上,还是傻傻的什么都不想,用最原始的方式吧,哈哈...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值