我已将一个Java应用程序升级到Java 8。该应用程序严重依赖于HashMaps。当我运行基准测试时,看到的结果是不可预测的。对于某些输入,应用程序比以前运行得更快,但对于较大的输入,则始终较慢。
我已经检查了分析器,发现最耗时的操作是HashMap.get。我怀疑变化是由于Java 8中的HashMap修改造成的,但这可能并不是真的,因为我还改变了其他部分。
是否有一种简单的方法,可以将原始的Java 7 HashMap钩入我的Java 8应用程序中,以便我只更改hashmap实现,看看是否仍然观察到性能方面的变化。
以下是尝试模拟我的应用程序正在执行的内容的最小程序。基本思想是需要在应用程序中共享节点。在某个运行时点上,应根据一些整数属性检索或创建节点(如果节点不存在)。以下只使用两个整数,但在实际应用程序中,我具有一个、两个和三个整数键。
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class Test1 {
static int max_k1 = 500;
static int max_k2 = 500;
static Map<Node, Node> map;
static Random random = new Random();
public static void main(String[] args) {
for (int i = 0; i < 15; i++) {
long start = System.nanoTime();
run();
long end = System.nanoTime();
System.out.println((end - start) / 1000_000);
}
}
private static void run() {
map = new HashMap<>();
for (int i = 0; i < 10_000_000; i++) {
Node key = new Node(random.nextInt(max_k1), random.nextInt(max_k2));
Node val = getOrElseUpdate(key);
}
}
private static Node getOrElseUpdate(Node key) {
Node val;
if ((val = map.get(key)) == null) {
val = key;
map.put(key, val);
}
return val;
}
private static class Node {
private int k1;
private int k2;
public Node(int k1, int k2) {
this.k1 = k1;
this.k2 = k2;
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + k1;
result = 31 * result + k2;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof Node))
return false;
Node other = (Node) obj;
return k1 == other.k1 && k2 == other.k2;
}
}
}
基准测试较为简单,但这是在Java 8上运行15次的结果:
8143
7919
7984
7973
7948
7984
7931
7992
8038
7975
7924
7995
6903
7758
7627
这段内容是针对Java 7的:
7247
6955
6510
6514
6577
6489
6510
6570
6497
6482
6540
6462
6514
4603
6270
基准测试比较原始,所以我很感激如果有熟悉JMH或其他基准测试工具的人来运行它,但是从我观察的结果来看,Java 7的表现更好。有什么想法吗?