繁体   English   中英

当值使用硬编码字符串时,Java Map的性能最差

[英]Java Map got worst performance when value use hard-coded String

当我尝试对Java List / Map进行性能测试时,发现奇怪的性能结果。

我的测试逻辑分为数据准备和地图放置操作,分开的数据准备过程是正确计算地图操作成本的对象。

我可以理解不同的String创建方法会导致不同的性能结果,但是奇怪的是:使用一种特定的硬编码String会导致性能最差。

为什么这样的结果是这样。

这是测试代码,性能结果包含在测试用例方法注释中

package cn.codeworks.test;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Function;
import org.junit.Test;

public class TreeMapPerformanceTest {

  private static final int dataSize = 1000 * 1000;

  static class Pair {

    private final Integer key;
    private final String value;

    public Pair(Integer key, String value) {
      this.key = key;
      this.value = value;
    }

    public Integer getKey() {
      return key;
    }

    public String getValue() {
      return value;
    }

  }

  /**
   * time cost (3 times) = 196, 178, 186
   */
  @Test
  public void testPutPerformance_string_intern() {
    testPutPerformance((loc) -> new String("abc").intern());
  }

  /**
   * time cost (3 times) = 275, 317, 331
   */
  @Test
  public void testPutPerformance_string_new() {
    testPutPerformance((loc) -> new String("abc"));
  }

  /**
   * this case got bad performance
   * time cost (3 times) = 591, 565, 570
   */
  @Test
  public void testPutPerformance_string_hardcoded() {
    testPutPerformance((loc) -> "abc");
  }


  private void testPutPerformance(Function<Integer, String> stringCreateMethod) {
    // prepare data
    List<Pair> data = new ArrayList(dataSize);
    for (int i = 0; i < dataSize; i++) {
      Pair pair = new Pair(i, stringCreateMethod.apply(i));
      data.add(pair);
    }
    int size = data.size();

    // map operation
    Map<Integer, String> map = new TreeMap<>();

    long startTimeMillis = System.currentTimeMillis();

    for (int i = 0; i < size; i++) {
      Pair pair = data.get(i);
      map.put(pair.getKey(), pair.getValue());
    }

    long endTimeMillis = System.currentTimeMillis();
    System.out.println("time cost = " + (endTimeMillis - startTimeMillis));
  }

}

由于我没有遵循正确的流程,因此这是一个糟糕的基准。

添加JVM选项-XX:+PrintCompilation -verbose:gc ,再次运行测试,这是3个测试用例的结果:

[Full GC (Ergonomics)  114779K->32543K(270848K), 0.2512151 secs]
[Full GC (Ergonomics)  141433K->35541K(340992K), 0.3268599 secs]
[Full GC (Ergonomics)  59544K->55008K(227328K), 0.9451788 secs]

对于每种情况,都发生了一次完全GC ,而最慢的情况花费了最长的GC时间。

并且在添加了JVM选项-Xms512m -Xmx512m ,期望避免在测试用例运行期间使用Full GC,这之间的时间成本差异消失了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM