Class.forName() caching - java

In one of my applications I am using the following:
public void calculate (String className)
{
...
Class clazz = Class.forName(className);
...
}
This function is called several times / second.
There are about 10 possible class names.
And while I do realize there is some internal caching inside this function,
I think this caching is only available on native level.
For this reason I am starting to wonder if I should add my own caching.
private static Map<String,Class> classMap;
public void calculate (String className)
{
...
Class clazz = classMap.get(className);
if (clazz == null)
{
clazz = Class.forName(className);
if (classMap == null) classMap = new HashMap<String, Class>(40);
classMap.put(className, clazz);
}
...
}
Will this be a performance gain or does it really make no difference ?
Thank you in advance

I wrote a little script to calculate the execution time of both functions.
This is the Main class that I used.
public class Benchmark
{
public static void main(String... pArgs)
{
// prepare all data as much as possible.
// we don't want to do this while the clock is running.
Class[] classes = {Object.class, Integer.class, String.class, Short.class, Long.class, Double.class,
Float.class, Boolean.class, Character.class, Byte.class};
int cycles = 1000000;
String[] classNames = new String[cycles];
for (int i = 0; i < cycles; i++)
{
classNames[i] = classes[i % classes.length].getName();
}
// THERE ARE 2 IMPLEMENTATIONS - CLASSIC vs CACHING
Implementation impl = new Caching(); // or Classic();
// Start the clocks !
long startTime = System.currentTimeMillis();
for (int i = 0; i < cycles; i++)
{
impl.doStuff(classNames[i]);
}
long endTime = System.currentTimeMillis();
// calculate and display result
long totalTime = endTime - startTime;
System.out.println(totalTime);
}
}
Here is the classic implementation that uses Class.forName
private interface Implementation
{
Class doStuff(String clzName);
}
private static class Classic implements Implementation
{
#Override
public Class doStuff(String clzName)
{
try
{
return Class.forName(clzName);
}
catch (Exception e)
{
return null;
}
}
}
Here is the second implementation that uses a HashMap to cache the Class objects.
private static class Caching implements Implementation
{
private Map<String, Class> cache = new HashMap<String, Class>();
#Override
public Class doStuff(String clzName)
{
Class clz = cache.get(clzName);
if (clz != null) return clz;
try
{
clz = Class.forName(clzName);
cache.put(clzName, clz);
}
catch (Exception e)
{
}
return clz;
}
}
The results:
1100 ms without caching.
only 15 ms with caching.
Conclusion:
Is it a significant difference --> yes !
Does it matter for my application --> not at all.

Will this be a performance gain or does it really make no difference?
I would be astonished if it made a significant difference - and if you're only calling it "several times per second" (rather than, say, a million) it's really not worth optimizing.
You should at least try this in isolation in a benchmark before committing to this more complicated design. I would strongly expect Class.forName to be caching this anyway, and adding more complexity into your app does no good.

Class.forName() does two things:
it fetches a loaded class from the classloader
if no such class is found, it tries to load it.
Part #1 is pretty quick. #2 is where the real work starts (where the JVM might hit the hard disk or even the network, depending on the classloader). And if you pass the same parameters in, then all but the first invocations will never get to step #2.
So no: it's probably not worth optimizing.

No you shouldn't. Class.forName will not load the same class twice but will try to find the class among the loaded classes. It's done at native level and supposed to be very efficient.

Related

How to use the same hashmap in multiple threads

I have a Hashmap that is created for each "mailer" class and each "agent" class creates a mailer.
My problem is that each of my "agents" creates a "mailer" that in turn creates a new hashmap.
What I'm trying to do is to create one Hashmap that will be used by all the agents(every agent is a thread).
This is the Agent class:
public class Agent implements Runnable {
private int id;
private int n;
private Mailer mailer;
private static int counter;
private List<Integer> received = new ArrayList<Integer>();
#Override
public void run() {
System.out.println("Thread has started");
n = 10;
if (counter < n - 1) {
this.id = ThreadLocalRandom.current().nextInt(0, n + 1);
counter++;
}
Message m = new Message(this.id, this.id);
this.mailer.getMap().put(this.id, new ArrayList<Message>());
System.out.println(this.mailer.getMap());
for (int i = 0; i < n; i++) {
if (i == this.id) {
continue;
}
this.mailer.send(i, m);
}
for (int i = 0; i < n; i++) {
if (i == this.id) {
continue;
}
if (this.mailer.getMap().get(i) == null) {
continue;
} else {
this.received.add(this.mailer.readOne(this.id).getContent());
}
}
System.out.println(this.id + "" + this.received);
}
}
This is the Mailer class :
public class Mailer {
private HashMap<Integer, List<Message>> map = new HashMap<>();
public void send(int receiver, Message m) {
synchronized (map) {
while (this.map.get(receiver) == null) {
this.map.get(receiver);
}
if (this.map.get(receiver) == null) {
} else {
map.get(receiver).add(m);
}
}
}
public Message readOne(int receiver) {
synchronized (map) {
if (this.map.get(receiver) == null) {
return null;
} else if (this.map.get(receiver).size() == 0) {
return null;
} else {
Message m = this.map.get(receiver).get(0);
this.map.get(receiver).remove(0);
return m;
}
}
}
public HashMap<Integer, List<Message>> getMap() {
synchronized (map) {
return map;
}
}
}
I have tried so far :
Creating the mailer object inside the run method in agent.
Going by the idea (based on your own answer to this question) that you made the map static, you've made 2 mistakes.
do not use static
static means there is one map for the entire JVM you run this on. This is not actually a good thing: Now you can't create separate mailers on one JVM in the future, and you've made it hard to test stuff.
You want something else: A way to group a bunch of mailer threads together (these are all mailers for the agent), but a bit more discerning than a simple: "ALL mailers in the ENTIRE system are all the one mailer for the one agent that will ever run".
A trivial way to do this is to pass the map in as argument. Alternatively, have the map be part of the agent, and pass the agent to the mailer constructor, and have the mailer ask the agent for the map every time.
this is not thread safe
Thread safety is a crucial concept to get right, because the failure mode if you get it wrong is extremely annoying: It may or may not work, and the JVM is free to base whether it'll work right this moment or won't work on the phase of the moon or the flip of a coin: The JVM is given room to do whatever it feels like it needs to, in order to have a JVM that can make full use of the CPU's powers regardless of which CPU and operating system your app is running on.
Your code is not thread safe.
In any given moment, if 2 threads are both referring to the same field, you've got a problem: You need to ensure that this is done 'safely', and the compiler nor the runtime will throw errors if you fail to do this, but you will get bizarre behaviour because the JVM is free to give you caches, refuse to synchronize things, make ghosts of data appear, and more.
In this case the fix is near-trivial: Use java.util.concurrent.ConcurrentHashMap instead, that's all you'd have to do to make this safe.
Whenever you're interacting with a field that doesn't have a convenient 'typesafe' type, or you're messing with the field itself (one thread assigns a new value to the field, another reads it - you don't do that here, there is just the one field that always points at the same map, but you're messing with the map) - you need to use synchronized and/or volatile and/or locks from the java.util.concurrent package and in general it gets very complicated. Concurrent programming is hard.
I was able to solve this by changing the mailer to static in the Agent class

Simple performance test, different results

I am made performance test of collection, but every time, when i am starting test, i have different results. Why it is happening and what can i do for take correct results? I am think my problem with option VM.
public class PerformanceTest {
private static void addToTheBeginTest() {
String nameOfMethod = "Method add 250_000 result: ";
List<Integer> arrayList = new ArrayList<>();
StopWatch.start();
for (int i = 0; i < 250_000; i++) {
arrayList.add(0, 1);
}
long resultAL = StopWatch.getElapsedTime();
outputInFile(nameOfMethod, resultAL);
}
private static void outputInFile(String nameOfMethod, long resultAl) {
File outputFile = new File("D:\\Idea Project\\ExperimentalProject\\src\\SimplePerformance\\");
outputFile.mkdir();
try (FileWriter writer = new FileWriter("D:\\Idea Project\\ExperimentalProject\\src\\SimplePerformance\\SimplePerformanceTest.txt", true)) {
writer.write(nameOfMethod);
writer.write(String.valueOf(resultAl) + " mc \n");
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
class StopWatch {
private static long result;
public static void start() {
result = System.currentTimeMillis();
}
public static long getElapsedTime() {
return System.currentTimeMillis() - result;
}
}
Results of 3 times
The reasons for this have already been explained by other answers.
The easiest way to handle this is to run each test x1000 and take an average. You should find the results more consistent.
The exact amount of resources available before running a code keeps on varying every ms. It is not possible to keep it constant on regular computers.
jvms do optimisations under the hood the more time a particular code is run. You should look into micro bench marking. There's a whole bunch of things that need to be done in order to get accurate results.

java optimization nitpick: is it faster to cast something and let it throw exception than calling instanceof to check before cast?

Before anyone says anything I'm asking this out of curiosity only; I'm not planning to do any premature optimization based off of this answer.
My question is about speed in using reflection and casting. The standard saying is 'reflection is slow'. My question is what part exactly is slow, and why; particularly in comparing if something is a parent of another instance.
I'm pretty confident that just comparing the class of an object to another Class object is about as fast as any comparison, presumably just doing direct comparison of singleton objects that are already stored int he Object's state; but what if one class is a parent of the other?
I usually think of instanceof as being about as fast as regular class checking, but today I thought about it and it seems that some reflection has to happen 'under the scenes' for instanceof to work. I checked online and found a few places where someone said instanceof is slow; presumably due to reflection required to compare the parent of an object?
This lead to the next question, what about just casting. If I cast something as an object it's not I get a ClassCastException. But this doesn't happen if a cast an object to a parent of itself. Essentially I'm doing an instanceof call, or logic to that effect, when I do the cast at run time am I not? I've never heard anyone hint that casting an object could be slow before. Admittedly not all casts are to a parent of the provided object, but plenty of casts are to parent classes. Yet never has anyone hinted at all that this could be slow.
So which is it. Is instanceof really not that slow? Are both instanceof and casting to parent class kind of slow? or is there some reason a cast can be done faster then an instanceof call?
As always try it and see in your particular situations, but:
-Exceptions are expensive, remarkably so.
-Using exceptions for code flow is almost always a bad idea
Edit:
Ok I was interested so I wrote a quick test system
public class Test{
public Test(){
B b=new B();
C c=new C();
for(int i=0;i<10000;i++){
testUsingInstanceOf(b);
testUsingInstanceOf(c);
testUsingException(b);
testUsingException(c);
}
}
public static void main(String[] args){
Test test=new Test();
}
public static boolean testUsingInstanceOf(A possiblyB){
if (possiblyB instanceof B){
return true;
}else{
return false;
}
}
public static boolean testUsingException(A possiblyB){
try{
B b=(B)possiblyB;
return true;
}catch(Exception e){
return false;
}
}
private class A{
}
private class B extends A{
}
private class C extends A{
}
}
Profile results:
by InstanceOf: 4.43 ms
by Exception: 79.4 ms
as I say, remarkably expensive
And even when its always going to be a B (simulating when you're 99% sure its B you just need to be sure its still no faster:
Profile results when always B:
by InstanceOf: 4.48 ms
by Exception: 4.51 ms
There is a general answer and a particular answer.
General case
if (/* guard against exception */) {
/* do something that would throw an exception */
} else {
/* recover */
}
// versus
try {
/* do something that would throw an exception */
} catch (TheException ex) {
/* recover */
}
It is a fact that creating/throwing/catching an exception is expensive. And they are likely to be significantly more expensive than doing the test. However, that doesn't mean that the "test first" version is always faster. This is because in the "test first" version, the tests may actually be performed: first time in the if, and second time in the code that would throw the exception.
When you take that into account, it is clear that if the cost of the (extra) test is large enough and the relative frequency of exceptions is small enough, "test first" will actually be slower. For example, in:
if (file.exists() && file.isReadable()) {
is = new FileInputStream(file);
} else {
System.err.println("missing file");
}
versus
try {
is = new FileInputStream(file);
} catch (IOException ex) {
System.err.println("missing file");
}
the "test first" approach performs 2 extra system calls, and system calls are expensive. If the "missing file" scenario is also unusual ....
The second confounding factor is that the most recent HotSpot JIT compilers do some significant optimization of exceptions. In particular, if the JIT compiler can figure out that the state of the exception object is not used, it may turn the exception create/throw/catch into a simple jump instruction.
The specific case of instanceof
In this case we are most likely comparing these two:
if (o instanceof Foo) {
Foo f = (Foo) o;
/* ... */
}
// versus
try {
Foo f = (Foo) o;
} catch (ClassCastException ex) {
/* */
}
Here a second optimization occurs. An instanceof followed by a type cast is a common pattern. A HotSpot JIT compiler can often eliminate the dynamic type check that is performed by the type cast ... since this is repeating a test that just succeeded. When you factor this in, it the "test first" version cannot be slower than the "exception" version ... even if the latter is optimized to a jump.
Unfortunately, Richard's code can't be run directly to produce timings. I've modified the question slightly, assuming that you really want "if A is a B, do something on B", rather than just asking the question "is A a B?". Here is the test code.
UPDATED FROM ORIGINAL
It was rather challenging to write trivial code that the HotSpot compiler didn't reduce to nothing, but I think the following is good:
package net.redpoint.utils;
public class Scratch {
public long counter = 0;
public class A {
public void inc() { counter++; }
}
public class B extends A {
public void inc() { counter++; }
}
public class C extends A {
public void inc() { counter++; }
}
public A[] a = new A[3];
public void test() {
a[0] = new A();
a[1] = new B();
a[2] = new C();
int iter = 100000000;
long start = System.nanoTime();
for(int i = iter; i > 0; i--) {
testUsingInstanceOf(a[i%3]);
}
long end = System.nanoTime();
System.out.println("instanceof: " + iter / ((end - start) / 1000000000.0) + " per second");
start = System.nanoTime();
for(int i = iter; i > 0; i--) {
testUsingException(a[i%3]);
}
end = System.nanoTime();
System.out.println("try{}: " + iter / ((end - start) / 1000000000.0) + " per second");
start = System.nanoTime();
for(int i = iter; i > 0; i--) {
testUsingClassName(a[i%3]);
}
end = System.nanoTime();
System.out.println("classname: " + iter / ((end - start) / 1000000000.0) + " per second");
}
public static void main(String[] args) {
Scratch s = new Scratch();
s.test();
}
public void testUsingInstanceOf(A possiblyB){
if (possiblyB instanceof B){
((B)possiblyB).inc();
}
}
public void testUsingException(A possiblyB){
try{
((B)possiblyB).inc();
} catch(Exception e){
}
}
public void testUsingClassName(A possiblyB){
if (possiblyB.getClass().getName().equals("net.redpoint.utils.Scratch$B")){
((B)possiblyB).inc();
}
}
}
The resulting output:
instanceof: 4.573174070960945E8 per second
try{}: 3.926650051387284E8 per second
classname: 7.689439655530204E7 per second
Test was performed using Oracle JRE7 SE on Windows 8 x64, with Intel i7 sandy bridge CPU.
If the cast can throw an exception, it means that it's doing implicitly what instanceof would do. So, in both cases you are implicitly using reflection, probably in exactly the same way.
The difference is that if the result of instanceof comes back false, no more reflection is happening. If a cast fails and an exception is thrown, you'll have unrolling of the execution stack and, quite possibly, more reflection (for the runtime to determine the correct catch block, based on whether the thrown exception object is an instance of the type to be caught).
The above logic tells me that an instanceof check should be faster. Of course, benchmarking for your particular case would give you the definitive answer.
I don't think you would find one being clearly better than the other.
For instanceof, the work done use memory and cpu time. Creating a exception use memory and cpu time also. Which use less of each, only a well done benchmark would give you that answer.
Coding-wise, I would prefer to see a instanceof rather than casting and having to manage exceptions.

Why are interfaces slower than abstract classes [duplicate]

This is question comes in mind when I finding difference between abstract class and interface.
In this post I came to know that interfaces are slow as they required extra indirection.
But I am not getting what type of indirection required by the interface and not by the abstract class or concrete class.Please clarify on it.
Thanks in advance
There are many performance myths, and some were probably true several years ago, and some might still be true on VMs that don't have a JIT.
The Android documentation (remember that Android don't have a JVM, they have Dalvik VM) used to say that invoking a method on an interfaces was slower than invoking it on a class, so they were contributing to spreading the myth (it's also possible that it was slower on the Dalvik VM before they turned on the JIT). The documentation does now say:
Performance Myths
Previous versions of this document made various misleading claims. We
address some of them here.
On devices without a JIT, it is true that invoking methods via a
variable with an exact type rather than an interface is slightly more
efficient. (So, for example, it was cheaper to invoke methods on a
HashMap map than a Map map, even though in both cases the map was a
HashMap.) It was not the case that this was 2x slower; the actual
difference was more like 6% slower. Furthermore, the JIT makes the two
effectively indistinguishable.
Source: Designing for performance on Android
The same thing is probably true for the JIT in the JVM, it would be very odd otherwise.
If in doubt, measure it. My results showed no significant difference. When run, the following program produced:
7421714 (abstract)
5840702 (interface)
7621523 (abstract)
5929049 (interface)
But when I switched the places of the two loops:
7887080 (interface)
5573605 (abstract)
7986213 (interface)
5609046 (abstract)
It appears that abstract classes are slightly (~6%) faster, but that should not be noticeable; These are nanoseconds. 7887080 nanoseconds are ~7 milliseconds. That makes it a difference of 0.1 millis per 40k invocations (Java version: 1.6.20)
Here's the code:
public class ClassTest {
public static void main(String[] args) {
Random random = new Random();
List<Foo> foos = new ArrayList<Foo>(40000);
List<Bar> bars = new ArrayList<Bar>(40000);
for (int i = 0; i < 40000; i++) {
foos.add(random.nextBoolean() ? new Foo1Impl() : new Foo2Impl());
bars.add(random.nextBoolean() ? new Bar1Impl() : new Bar2Impl());
}
long start = System.nanoTime();
for (Foo foo : foos) {
foo.foo();
}
System.out.println(System.nanoTime() - start);
start = System.nanoTime();
for (Bar bar : bars) {
bar.bar();
}
System.out.println(System.nanoTime() - start);
}
abstract static class Foo {
public abstract int foo();
}
static interface Bar {
int bar();
}
static class Foo1Impl extends Foo {
#Override
public int foo() {
int i = 10;
i++;
return i;
}
}
static class Foo2Impl extends Foo {
#Override
public int foo() {
int i = 10;
i++;
return i;
}
}
static class Bar1Impl implements Bar {
#Override
public int bar() {
int i = 10;
i++;
return i;
}
}
static class Bar2Impl implements Bar {
#Override
public int bar() {
int i = 10;
i++;
return i;
}
}
}
An object has a "vtable pointer" of some kind which points to a "vtable" (method pointer table) for its class ("vtable" might be the wrong terminology, but that's not important). The vtable has pointers to all the method implementations; each method has an index which corresponds to a table entry. So, to call a class method, you just look up the corresponding method (using its index) in the vtable. If one class extends another, it just has a longer vtable with more entries; calling a method from the base class still uses the same procedure: that is, look up the method by its index.
However, in calling a method from an interface via an interface reference, there must be some alternative mechanism to find the method implementation pointer. Because a class can implement multiple interfaces, it's not possible for the method to always have the same index in the vtable (for instance). There are various possible ways to resolve this, but no way that is quite as efficient as simple vtable dispatch.
However, as mentioned in the comments, it probably won't make much difference with a modern Java VM implementation.
This is variation on Bozho example. It runs longer and re-uses the same objects so the cache size doesn't matter so much. I also use an array so there is no overhead from the iterator.
public static void main(String[] args) {
Random random = new Random();
int testLength = 200 * 1000 * 1000;
Foo[] foos = new Foo[testLength];
Bar[] bars = new Bar[testLength];
Foo1Impl foo1 = new Foo1Impl();
Foo2Impl foo2 = new Foo2Impl();
Bar1Impl bar1 = new Bar1Impl();
Bar2Impl bar2 = new Bar2Impl();
for (int i = 0; i < testLength; i++) {
boolean flip = random.nextBoolean();
foos[i] = flip ? foo1 : foo2;
bars[i] = flip ? bar1 : bar2;
}
long start;
start = System.nanoTime();
for (Foo foo : foos) {
foo.foo();
}
System.out.printf("The average abstract method call was %.1f ns%n", (double) (System.nanoTime() - start) / testLength);
start = System.nanoTime();
for (Bar bar : bars) {
bar.bar();
}
System.out.printf("The average interface method call was %.1f ns%n", (double) (System.nanoTime() - start) / testLength);
}
prints
The average abstract method call was 4.2 ns
The average interface method call was 4.1 ns
if you swap the order the tests are run you get
The average interface method call was 4.2 ns
The average abstract method call was 4.1 ns
There is more difference in how you run the test than which one you chose.
I got the same result with Java 6 update 26 and OpenJDK 7.
BTW: If you add a loop which only call the same object each time, you get
The direct method call was 2.2 ns
I tried to write a test that would quantify all of the various ways methods might be invoked. My findings show that it is not whether a method is an interface method or not that matters, but rather the type of the reference through which you are calling it. Calling an interface method through a class reference is much faster (relative to the number of calls) than calling the same method on the same class via an interface reference.
The results for 1,000,000 calls are...
interface method via interface reference: (nanos, millis) 5172161.0, 5.0
interface method via abstract reference: (nanos, millis) 1893732.0, 1.8
interface method via toplevel derived reference: (nanos, millis) 1841659.0, 1.8
Concrete method via concrete class reference: (nanos, millis) 1822885.0, 1.8
Note that the first two lines of the results are calls to the exact same method, but via different references.
And here is the code...
package interfacetest;
/**
*
* #author rpbarbat
*/
public class InterfaceTest
{
static public interface ITest
{
public int getFirstValue();
public int getSecondValue();
}
static abstract public class ATest implements ITest
{
int first = 0;
#Override
public int getFirstValue()
{
return first++;
}
}
static public class TestImpl extends ATest
{
int second = 0;
#Override
public int getSecondValue()
{
return second++;
}
}
static public class Test
{
int value = 0;
public int getConcreteValue()
{
return value++;
}
}
static int loops = 1000000;
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
// Get some various pointers to the test classes
// To Interface
ITest iTest = new TestImpl();
// To abstract base
ATest aTest = new TestImpl();
// To impl
TestImpl testImpl = new TestImpl();
// To concrete
Test test = new Test();
System.out.println("Method call timings - " + loops + " loops");
StopWatch stopWatch = new StopWatch();
// Call interface method via interface reference
stopWatch.start();
for (int i = 0; i < loops; i++)
{
iTest.getFirstValue();
}
stopWatch.stop();
System.out.println("interface method via interface reference: (nanos, millis)" + stopWatch.getElapsedNanos() + ", " + stopWatch.getElapsedMillis());
// Call interface method via abstract reference
stopWatch.start();
for (int i = 0; i < loops; i++)
{
aTest.getFirstValue();
}
stopWatch.stop();
System.out.println("interface method via abstract reference: (nanos, millis)" + stopWatch.getElapsedNanos() + ", " + stopWatch.getElapsedMillis());
// Call derived interface via derived reference
stopWatch.start();
for (int i = 0; i < loops; i++)
{
testImpl.getSecondValue();
}
stopWatch.stop();
System.out.println("interface via toplevel derived reference: (nanos, millis)" + stopWatch.getElapsedNanos() + ", " + stopWatch.getElapsedMillis());
// Call concrete method in concrete class
stopWatch.start();
for (int i = 0; i < loops; i++)
{
test.getConcreteValue();
}
stopWatch.stop();
System.out.println("Concrete method via concrete class reference: (nanos, millis)" + stopWatch.getElapsedNanos() + ", " + stopWatch.getElapsedMillis());
}
}
package interfacetest;
/**
*
* #author rpbarbat
*/
public class StopWatch
{
private long start;
private long stop;
public StopWatch()
{
start = 0;
stop = 0;
}
public void start()
{
stop = 0;
start = System.nanoTime();
}
public void stop()
{
stop = System.nanoTime();
}
public float getElapsedNanos()
{
return (stop - start);
}
public float getElapsedMillis()
{
return (stop - start) / 1000;
}
public float getElapsedSeconds()
{
return (stop - start) / 1000000000;
}
}
This was using the Oracles JDK 1.6_24. Hope this helps put this question to bed...
Regards,
Rodney Barbati
Interfaces are slower than abstract class as run time decision of method invocation would add little penalty of time,
However as JIT comes in picture which will take care of repeated calls of same method hence you may see the performance lag only in first call which is also very minimal,
Now for Java 8, they almost made abstract class useless by adding default & static function,

Why are interface method invocations slower than concrete invocations?

This is question comes in mind when I finding difference between abstract class and interface.
In this post I came to know that interfaces are slow as they required extra indirection.
But I am not getting what type of indirection required by the interface and not by the abstract class or concrete class.Please clarify on it.
Thanks in advance
There are many performance myths, and some were probably true several years ago, and some might still be true on VMs that don't have a JIT.
The Android documentation (remember that Android don't have a JVM, they have Dalvik VM) used to say that invoking a method on an interfaces was slower than invoking it on a class, so they were contributing to spreading the myth (it's also possible that it was slower on the Dalvik VM before they turned on the JIT). The documentation does now say:
Performance Myths
Previous versions of this document made various misleading claims. We
address some of them here.
On devices without a JIT, it is true that invoking methods via a
variable with an exact type rather than an interface is slightly more
efficient. (So, for example, it was cheaper to invoke methods on a
HashMap map than a Map map, even though in both cases the map was a
HashMap.) It was not the case that this was 2x slower; the actual
difference was more like 6% slower. Furthermore, the JIT makes the two
effectively indistinguishable.
Source: Designing for performance on Android
The same thing is probably true for the JIT in the JVM, it would be very odd otherwise.
If in doubt, measure it. My results showed no significant difference. When run, the following program produced:
7421714 (abstract)
5840702 (interface)
7621523 (abstract)
5929049 (interface)
But when I switched the places of the two loops:
7887080 (interface)
5573605 (abstract)
7986213 (interface)
5609046 (abstract)
It appears that abstract classes are slightly (~6%) faster, but that should not be noticeable; These are nanoseconds. 7887080 nanoseconds are ~7 milliseconds. That makes it a difference of 0.1 millis per 40k invocations (Java version: 1.6.20)
Here's the code:
public class ClassTest {
public static void main(String[] args) {
Random random = new Random();
List<Foo> foos = new ArrayList<Foo>(40000);
List<Bar> bars = new ArrayList<Bar>(40000);
for (int i = 0; i < 40000; i++) {
foos.add(random.nextBoolean() ? new Foo1Impl() : new Foo2Impl());
bars.add(random.nextBoolean() ? new Bar1Impl() : new Bar2Impl());
}
long start = System.nanoTime();
for (Foo foo : foos) {
foo.foo();
}
System.out.println(System.nanoTime() - start);
start = System.nanoTime();
for (Bar bar : bars) {
bar.bar();
}
System.out.println(System.nanoTime() - start);
}
abstract static class Foo {
public abstract int foo();
}
static interface Bar {
int bar();
}
static class Foo1Impl extends Foo {
#Override
public int foo() {
int i = 10;
i++;
return i;
}
}
static class Foo2Impl extends Foo {
#Override
public int foo() {
int i = 10;
i++;
return i;
}
}
static class Bar1Impl implements Bar {
#Override
public int bar() {
int i = 10;
i++;
return i;
}
}
static class Bar2Impl implements Bar {
#Override
public int bar() {
int i = 10;
i++;
return i;
}
}
}
An object has a "vtable pointer" of some kind which points to a "vtable" (method pointer table) for its class ("vtable" might be the wrong terminology, but that's not important). The vtable has pointers to all the method implementations; each method has an index which corresponds to a table entry. So, to call a class method, you just look up the corresponding method (using its index) in the vtable. If one class extends another, it just has a longer vtable with more entries; calling a method from the base class still uses the same procedure: that is, look up the method by its index.
However, in calling a method from an interface via an interface reference, there must be some alternative mechanism to find the method implementation pointer. Because a class can implement multiple interfaces, it's not possible for the method to always have the same index in the vtable (for instance). There are various possible ways to resolve this, but no way that is quite as efficient as simple vtable dispatch.
However, as mentioned in the comments, it probably won't make much difference with a modern Java VM implementation.
This is variation on Bozho example. It runs longer and re-uses the same objects so the cache size doesn't matter so much. I also use an array so there is no overhead from the iterator.
public static void main(String[] args) {
Random random = new Random();
int testLength = 200 * 1000 * 1000;
Foo[] foos = new Foo[testLength];
Bar[] bars = new Bar[testLength];
Foo1Impl foo1 = new Foo1Impl();
Foo2Impl foo2 = new Foo2Impl();
Bar1Impl bar1 = new Bar1Impl();
Bar2Impl bar2 = new Bar2Impl();
for (int i = 0; i < testLength; i++) {
boolean flip = random.nextBoolean();
foos[i] = flip ? foo1 : foo2;
bars[i] = flip ? bar1 : bar2;
}
long start;
start = System.nanoTime();
for (Foo foo : foos) {
foo.foo();
}
System.out.printf("The average abstract method call was %.1f ns%n", (double) (System.nanoTime() - start) / testLength);
start = System.nanoTime();
for (Bar bar : bars) {
bar.bar();
}
System.out.printf("The average interface method call was %.1f ns%n", (double) (System.nanoTime() - start) / testLength);
}
prints
The average abstract method call was 4.2 ns
The average interface method call was 4.1 ns
if you swap the order the tests are run you get
The average interface method call was 4.2 ns
The average abstract method call was 4.1 ns
There is more difference in how you run the test than which one you chose.
I got the same result with Java 6 update 26 and OpenJDK 7.
BTW: If you add a loop which only call the same object each time, you get
The direct method call was 2.2 ns
I tried to write a test that would quantify all of the various ways methods might be invoked. My findings show that it is not whether a method is an interface method or not that matters, but rather the type of the reference through which you are calling it. Calling an interface method through a class reference is much faster (relative to the number of calls) than calling the same method on the same class via an interface reference.
The results for 1,000,000 calls are...
interface method via interface reference: (nanos, millis) 5172161.0, 5.0
interface method via abstract reference: (nanos, millis) 1893732.0, 1.8
interface method via toplevel derived reference: (nanos, millis) 1841659.0, 1.8
Concrete method via concrete class reference: (nanos, millis) 1822885.0, 1.8
Note that the first two lines of the results are calls to the exact same method, but via different references.
And here is the code...
package interfacetest;
/**
*
* #author rpbarbat
*/
public class InterfaceTest
{
static public interface ITest
{
public int getFirstValue();
public int getSecondValue();
}
static abstract public class ATest implements ITest
{
int first = 0;
#Override
public int getFirstValue()
{
return first++;
}
}
static public class TestImpl extends ATest
{
int second = 0;
#Override
public int getSecondValue()
{
return second++;
}
}
static public class Test
{
int value = 0;
public int getConcreteValue()
{
return value++;
}
}
static int loops = 1000000;
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
// Get some various pointers to the test classes
// To Interface
ITest iTest = new TestImpl();
// To abstract base
ATest aTest = new TestImpl();
// To impl
TestImpl testImpl = new TestImpl();
// To concrete
Test test = new Test();
System.out.println("Method call timings - " + loops + " loops");
StopWatch stopWatch = new StopWatch();
// Call interface method via interface reference
stopWatch.start();
for (int i = 0; i < loops; i++)
{
iTest.getFirstValue();
}
stopWatch.stop();
System.out.println("interface method via interface reference: (nanos, millis)" + stopWatch.getElapsedNanos() + ", " + stopWatch.getElapsedMillis());
// Call interface method via abstract reference
stopWatch.start();
for (int i = 0; i < loops; i++)
{
aTest.getFirstValue();
}
stopWatch.stop();
System.out.println("interface method via abstract reference: (nanos, millis)" + stopWatch.getElapsedNanos() + ", " + stopWatch.getElapsedMillis());
// Call derived interface via derived reference
stopWatch.start();
for (int i = 0; i < loops; i++)
{
testImpl.getSecondValue();
}
stopWatch.stop();
System.out.println("interface via toplevel derived reference: (nanos, millis)" + stopWatch.getElapsedNanos() + ", " + stopWatch.getElapsedMillis());
// Call concrete method in concrete class
stopWatch.start();
for (int i = 0; i < loops; i++)
{
test.getConcreteValue();
}
stopWatch.stop();
System.out.println("Concrete method via concrete class reference: (nanos, millis)" + stopWatch.getElapsedNanos() + ", " + stopWatch.getElapsedMillis());
}
}
package interfacetest;
/**
*
* #author rpbarbat
*/
public class StopWatch
{
private long start;
private long stop;
public StopWatch()
{
start = 0;
stop = 0;
}
public void start()
{
stop = 0;
start = System.nanoTime();
}
public void stop()
{
stop = System.nanoTime();
}
public float getElapsedNanos()
{
return (stop - start);
}
public float getElapsedMillis()
{
return (stop - start) / 1000;
}
public float getElapsedSeconds()
{
return (stop - start) / 1000000000;
}
}
This was using the Oracles JDK 1.6_24. Hope this helps put this question to bed...
Regards,
Rodney Barbati
Interfaces are slower than abstract class as run time decision of method invocation would add little penalty of time,
However as JIT comes in picture which will take care of repeated calls of same method hence you may see the performance lag only in first call which is also very minimal,
Now for Java 8, they almost made abstract class useless by adding default & static function,

Categories

Resources