Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How expensive is .getClass() in Java?

Tags:

java

I'm in the process of porting over a certain data processing algorithm from Java to C++. The reason for re-writing the code is portability, it needs to run in environments where Java is not available. However, as a side benefit some performance improvement was expected.

Basically, the algorithm reads data from a graph made up of objects with pointers to each other and then computes a result. During the computation numerous object allocations are made, so perhaps this is responsible for the slowdown. The thing is, the C++ code currently runs about 10 times faster than the old Java code. This was really unexpected. I only thought I'd see an improvement of maybe 50-60%.

Unfortunately, I'm not at liberty to post the code here for analysis. It's several thousand lines, so I'm not sure how convenient that would be anyway.

The thing is, the algorithm is almost exactly the same. The only major difference I can think of is in Java there are many daughter classes of a single super class and if(object.getClass() == daughterx.class) is called many times during the computation whereas in the C++ code only one general class is used (since there are few code differences between the daughter classes) and a simple integer comparison is used eg. if(object->type == 15)

How expensive is the Object.getClass() method in Java? What exactly is happening at the low-level when this method is invoked?

like image 860
mimicocotopus Avatar asked Sep 01 '12 06:09

mimicocotopus


People also ask

What does getClass () do in Java?

The getClass() method of Writer Class in Java is used to get the parent Class of this Writer instance. This method does not accepts any parameter and returns the required Class details. Parameters: This method accepts does not accepts any parameter.

What is getClass () getName () in Java?

The getName() method of java Class class is used to get the name of the entity, and that entity can be class, interface, array, enum, method, etc. of the class object. Element Type.

Is Instanceof slow in Java?

Instanceof is very fast. It boils down to a bytecode that is used for class reference comparison.


3 Answers

How expensive is the Object.getClass() method in Java?

Based on my knowledge of how it is implemented in non-mainstream JVMs, it is cheap

What exactly is happening at the low-level when this method is invoked?

Typically ...

  1. Extract the class index from the object's header (2 or 3 instructions)
  2. Lookup the class descriptor from the class index (2 or 3 instructions)
  3. Fetch and return the Class object reference from the class descriptor (2 or 3 instructions)

The thing is, the C++ code currently runs about 10 times faster than the old Java code.

I expect that the performance bottleneck is somewhere else. You should try profiling the Java code before jumping to any conclusions as to why it was slower.

like image 52
Stephen C Avatar answered Oct 23 '22 03:10

Stephen C


The most likely case for a 10x difference is that the JVM wasn't warmed up completely. If you don't do this you can see more than 10x performance difference even in Java. I would try running in batches of 10,000 and ignore the first few runs.

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);
}

prints

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

From the first to the last run, the performance has improved by a factor of 3000x

like image 31
Peter Lawrey Avatar answered Oct 23 '22 05:10

Peter Lawrey


It's not likely to be the sole factor in the performance difference. Unfortunately, without a much more complete picture of what your code actually is doing, it's going to be really hard to tell you what's going on.

In my experience there's no reason Java should be 10x slower than C++. I would probably start with a profiler and see where it points to understand the problem, rather than guessing.

like image 28
Steven Schlansker Avatar answered Oct 23 '22 03:10

Steven Schlansker