我正在将某个数据处理算法从Java移植到C ++。重写代码的原因是可移植性,它需要在Java不可用的环境中运行。然而,作为附带的好处,预计会有一些性能提升。
基本上,算法从由彼此指针的对象组成的图中读取数据,然后计算结果。在计算过程中会进行大量的对象分配,因此这可能是造成减速的原因。问题是,C ++代码目前运行速度比旧Java代码快10倍。这真是出乎意料。我只觉得我会看到改善50-60%。
不幸的是,我无权在此处发布代码进行分析。这是几千行,所以我不确定无论多么方便。
事实是,算法几乎完全相同。我能想到的唯一主要区别是在Java中有一个超级类的子类很多,if(object.getClass()== daughterx.class)在计算过程中被多次调用而在C ++代码中只有一个通用使用class(因为子类之间的代码差异很少)并且使用简单的整数比较,例如。 if(object-> type == 15)Java中的Object.getClass()方法有多贵?调用此方法时,在低级别发生了什么?
答案 0 :(得分:12)
Java中的Object.getClass()方法有多贵?
根据我对如何在非主流JVM中实现的知识,它很便宜
调用此方法时,在低级别发生了什么?
通常......
Class
对象引用(2或3条指令)问题是,C ++代码目前运行速度比旧Java代码快10倍。
我希望性能瓶颈在其他地方。您应该尝试分析Java代码,然后再得出结论为什么它更慢。
答案 1 :(得分:7)
10倍差异的最可能的情况是JVM没有完全预热。如果不这样做,即使在Java中也可以看到超过10倍的性能差异。我会尝试分批运行10,000次并忽略前几次运行。
public static void main(String... args) throws IOException {
timeObjectGraph("First run", 1);
timeObjectGraph("Second run", 2);
timeObjectGraph("Next thousand", 1000);
for (int i = 0; i < 5; i++)
timeObjectGraph("Next ten thousand", 10000);
}
static int dontOptimiseAway = 0;
public static void timeObjectGraph(String desc, int runs) throws IOException {
long start = System.nanoTime();
for (int i = 0; i < runs; i++) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(Calendar.getInstance());
oos.close();
dontOptimiseAway = out.toByteArray().length;
}
long time = System.nanoTime() - start;
System.out.printf("%s took an avg time of %,d ns%n", desc, time / runs);
}
打印
First run took an avg time of 37,509,488 ns
Second run took an avg time of 439,054 ns
Next thousand took an avg time of 185,242 ns
Next ten thousand took an avg time of 41,698 ns
Next ten thousand took an avg time of 19,981 ns
Next ten thousand took an avg time of 11,541 ns
Next ten thousand took an avg time of 13,451 ns
Next ten thousand took an avg time of 11,289 ns
从第一次到最后一次运行,性能提高了3000倍
答案 2 :(得分:5)
这不太可能是性能差异的唯一因素。不幸的是,如果没有更完整的代码实际显示的内容,那么很难告诉你发生了什么。
根据我的经验,Java应该比C ++慢10倍。我可能会从一个分析器开始,看看它指向何处理解问题,而不是猜测。