10

我正在将某种数据处理算法从 Java 移植到 C++。重写代码的原因是可移植性,它需要在 Java 不可用的环境中运行。但是,作为附带的好处,一些性能改进是预期的。

基本上,该算法从由具有指针的对象组成的图中读取数据,然后计算结果。在计算过程中进行了大量的对象分配,所以这可能是导致速度变慢的原因。问题是,C++ 代码目前的运行速度比旧的 Java 代码快 10 倍。这真是出乎意料。我只以为我会看到可能有 50-60% 的改进。

不幸的是,我无权在此处发布代码以供分析。它有几千行,所以我不确定那会有多方便。

问题是,算法几乎完全相同。我能想到的唯一主要区别是在 Java 中,一个超类有许多子类,并且 if(object.getClass() == daughterx.class) 在计算过程中被调用了很多次,而在 C++ 代码中只有一个通用使用类(因为子类之间的代码差异很少)并使用简单的整数比较,例如。如果(对象->类型 == 15)

Java 中的 Object.getClass() 方法有多贵?调用此方法时,底层到底发生了什么?

4

3 回答 3

14

Java 中的 Object.getClass() 方法有多贵?

根据我对如何在非主流 JVM 中实现它的了解,它很便宜

调用此方法时,底层到底发生了什么?

通常 ...

  1. 从对象的标头中提取类索引(2 或 3 条指令)
  2. 从类索引中查找类描述符(2 或 3 条指令)
  3. 从类描述符中获取并返回Class对象引用(2 或 3 条指令)

问题是,C++ 代码目前的运行速度比旧的 Java 代码快 10 倍。

我希望性能瓶颈在其他地方。您应该先尝试分析 Java 代码,然后再得出关于它为什么变慢的任何结论。

于 2012-09-01T06:46:46.290 回答
8

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 倍

于 2012-09-01T07:04:41.900 回答
5

它不太可能是性能差异的唯一因素。不幸的是,如果没有更完整地了解您的代码实际在做什么,就很难告诉您发生了什么。

根据我的经验,Java 没有理由比 C++ 慢 10 倍。我可能会从探查器开始,看看它指向哪里来理解问题,而不是猜测。

于 2012-09-01T06:16:08.233 回答