When I try to do some performance test for Java List/Map, I find a strange performance result.
My test logic split into data prepare and map put operation, the separated data prepare process is object to calculate map operation cost correct.
I can understand the different String creation methods result into different performance result, but the strange thing was: use of one specific hard-coded String results in the worst performance.
Why this result is so.
Here is the test code, performance result is included in test case method comment
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));
}
}