2012-09-01 28 views
8

我正在将某种数据处理算法从Java移植到C++。重写代码的原因是可移植性,它需要在Java不可用的环境中运行。然而,作为一个副作用,预计会有一些性能改进。Java中.getClass()的价格是多少?

基本上,该算法从由指向对方的对象组成的图形中读取数据,然后计算结果。在计算过程中会进行许多对象分配,所以也许这是造成放缓的原因。事情是,C++代码目前的运行速度比旧Java代码快10倍。这真是出乎意料。我只以为我会看到50-60%的改善。

不幸的是,我不能随意在这里发布代码进行分析。这是几千行,所以我不知道这将是多么方便。

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

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

+5

的因素@ xlc0212提高也不是任何其他人不理解Java的! ;) – cheeken

+0

@cheeken它取决于JVM,没有JIT,我记得我从某处读过Java比python慢​​甚至更慢 –

+3

老实说这听起来像是一个没有问题的东西。是否值得您花时间对已弃用的代码进行基准测试和分析?除非你这样做,否则无法知道'.getClass()'是瓶颈。除非可以显着降低算法的总体复杂度(即从N平方运算变为log-N运算),并且数据集非常大,否则猜测不是有效的调试性能问题的方法。 –

回答

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倍

+0

为什么你使用Calendar.getInstance()?首先问题是关于getClass方法。第二个日历是**重**类创建的,所以Calendar.getInstance()**本身很昂贵**,而不是因为getClass在里面被调用。我认为这个例子不正确,或者你应该提供更明确的评论。 – Cherry

+2

@Cherry我使用了Calendar和ObjectOutputStream,因为这些代码对于一小段代码来说都很昂贵,这给出了一个现实的例子,即预热可以为大量代码带来多大的差异。 –

5

这不可能是性能差异的唯一因素。不幸的是,如果没有你的代码实际上做的更完整的图片,很难告诉你发生了什么事情。

根据我的经验,没有理由Java应该比C++慢10倍。我可能会从一个分析器开始,看看它指向哪个位置来理解问题,而不是猜测。

11

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

根据我的它是如何在非主流的JVM实现的知识,它是便宜

恰好在低级别正在发生什么调用此方法时?

通常...

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

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

我期望性能瓶颈是在别的地方。您应该尝试对Java代码进行分析,然后才能得出有关为何速度较慢的结论。

+6

+1虽然查找本身很便宜,但如果您有if(getClass()== SomeClass.class)序列,则这意味着显着的设计和性能问题。“这表明您需要更多的OO Design或OP,组合这些类,以便它可以使用开关或类似的功能。 –

相关问题