Java Method Invocation VS Using a Variable

Java Method invocation vs using a variable

Never code for performance, always code for readability. Let the compiler do the work.

They can improve the compiler/runtime to run good code faster and suddenly your "Fast" code is actually slowing the system down.

Java compiler & runtime optimizations seem to address more common/readable code first, so your "Optimized" code is more likely to be de-optimized at a later time than code that was just written cleanly.

Note:

This answer is referring to Java code "Tricks" like the question referenced, not bad programming that might raise the level of loops from an O(N) to an O(N^2). Generally write clean, DRY code and wait for an operation to take noticeably too long before fixing it. You will almost never reach this point unless you are a game designer.

Java: saving to a variable vs multiple function calls

If getValue() is a timeconsuming operation it will most likely be better to call it once only and store the value in a variable.

If you call it several times, you might not in practice get any performance improvements, depending on compiler optimizations.

Java storing an object vs directly calling its method?

I am primarily looking for arguments based on performance,

There is no difference. This local variable is essentially "free". If the method is called frequently, the JIT compiler will optimize the local variable away In any case, rhe object was just created, so its reference is in the first level cache

memory requirements,

If the optimizer doesn't remove it, a local variable may occupy a few extra bytes of space on the thread call stack. This space is reclaimed and reused when the method returns, if not sooner.

garbage collection,

The GC usually doesn't collect objects if there is a local variable pointing to it from a stack frame in a live thread. For long running methods, this may be significant: using a local variable means the object will be alive longer. For short running methods, there's virtually no difference.

etc

With a local variable, you can set a debugger break point on either of the lines. This allows you to inspect the state of the object after its creation and before the method call. Without a local variable you would have to dig deeper:

Foo foo = new Foo();
foo.method();

even if the difference is negligible.

If you're running in interpreted mode (as opposed to compiled to compiled to native), the execution of the local variable write and read (astore and aload byte code instructions) may be measurable.

When to use local variable instead of method?

First of all you should consider

  • Readability (which way is easier to understand and maintain).
  • Value consistency. If you get accustomed to cache the value in a variable, and at some case the value changes, then you might have a bug that is hard to spot.

Then comes the performance issues. For such trivial cases it might be equal or less efficient. Even if you used the variable 1000 times.

The compiler might translate if (someMethod()) -> if (true) if you are just returning a constant or reference (see Method inlining).


UPDATE

Just for recreational purposes (fooling around with homebrew pocket benchmark) (nothing serious like JMH).

  • Indicates that for simple cases there is no benefit of creating a variable to cache the result of method returning constants.
  • Weird thing I checked the generated bytecode (jdk 1.8.0_31) and Inlining$2#execute has 3 calls to calledStaticMethod (therefore no inlining on compilation). I must be missing something (Eclipse had its own compiler? options? misconceptions?) and the virtual machine JIT optimizer doing a terrific job.

source code (Inlining.java). Contains the almost harmless Benchmark class appended

// https://stackoverflow.com/questions/32500628/when-to-use-local-variable-instead-of-method
public class Inlining {
public static int calledStaticMethod() {
return 0;
}

public static void dumpValue(Object o) { // Fool compiler/JVM that value is going somewhere

}

public static void main(String[] args) {
float iterations = Benchmark.iterationsFor10sec(new Benchmark("cacheCall") {
@Override
public void execute(long iterations) {
int i1,i2,i3 = 0;
for (int i = 0; i < iterations; i++) {
int localVar = calledStaticMethod();
i1 = localVar;
i2 = i1 + localVar;
i3 = i2 + localVar;
}
dumpValue((Integer)i3);
}
});
System.out.printf("cacheCall: %10.0f\n", iterations);

iterations = Benchmark.iterationsFor10sec(new Benchmark("staticCall") {
@Override
public void execute(long iterations) {
int i1,i2,i3 = 0;
for (int i = 0; i < iterations; i++) {
i1 = calledStaticMethod();
i2 = i1 + calledStaticMethod();
i3 = i2 + calledStaticMethod();
}
dumpValue((Integer)i3);
}
});
System.out.printf("staticCall: %10.0f\n", iterations);

// borderline for inlining, as instance methods might be overridden.
iterations = Benchmark.iterationsFor10sec(new Benchmark("instanceCall") {
public int calledInstanceMethod() { return calledStaticMethod(); }
@Override
public void execute(long iterations) {
int i1,i2,i3 = 0;
for (int i = 0; i < iterations; i++) {
i1 = calledInstanceMethod();
i2 = i1 + calledInstanceMethod();
i3 = i2 + calledInstanceMethod();
}
dumpValue((Integer)i3);
}
});
System.out.printf("instanceCall: %10.0f\n", iterations);
}

}

abstract class Benchmark {
private String name;
public Benchmark(String s) { name = s; }
public String getName() { return name; }
public abstract void execute(long iterations);
public static float iterationsFor10sec(Benchmark bm) {
long t0 = System.nanoTime();
long ellapsed = 0L;
// Calibration. Run .5-1.0 seconds. Estimate iterations for .1 sec
final long runtimeCalibrate = (long)0.5e9; // half second
long iterations = 1L;
while (ellapsed < runtimeCalibrate) {
bm.execute(iterations);
iterations *= 2;
ellapsed = System.nanoTime() - t0;
}
iterations--; // Actually we executed 2^N - 1.
int innerIterations = (int) ((double)iterations * 1e8 /* nanos/inner */ / ellapsed);
if (innerIterations < 1) { innerIterations = 1; }
// run rest of the time
final long runtimeTotal = (long)1e10;
// outer loop
while (ellapsed < runtimeTotal) {
// delegate benchmark contains inner loop
bm.execute(innerIterations);
iterations += innerIterations;
ellapsed = System.nanoTime() - t0;
}
// execution time might exceed 10 seconds. rectify number of iterations
return (float)iterations * 1e10f /* nanos total */ / (float)ellapsed;

}
}

output:

cacheCall: 21414115328
staticCall: 21423159296
instanceCall: 21357850624

When Should You Use Get Methods vs Call Variables Directly?

Short answer: encapsulation.

A major benefit is to prevent other classes or modules, especially ones you don't write, from abusing the fields of the class you created.

Say for example you can an instance variable int which gets used as the denominator in one of your class methods. You know when you write your code to never assign this variable a value of 0, and you might even do some checking in the constructor. The problem is that some else might instantiate your class and later assign the instance variable a value of 0, thereby throwing an exception when they later invoke the method that uses this variable as a denominator (you cannot divide by 0).

Using a setter, you write code that guarantees the value of this variable will never be 0.

Another advantage is if you want to make instance variables read only after instantiating the class then you can make the variables private and define only getter methods and no setters.

Invoking a Class and Method Using Variables In Java

You need both a reference to the Class type and an instance of the class (unless the method you want to invoke is static). In your pseudo code you have the correct idea, all you need to do is a quick review of the javadoc for java.lang.Class and java.lang.reflect.Method

public class SettingsClass {

public static final boolean BOOT_TEST = true;
public static final String BOOT_CLASS = "MyClass";
public static final String BOOT_METHOD = "doMain";

}

public class MyClass {
public static void doMain() {
}
}

public class MainClass {

public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {

if(SettingsClass.BOOT_TEST) {
Class<?> clazz = Class.forName(SettingsClass.BOOT_CLASS);
Method m = clazz.getMethod(SettingsClass.BOOT_METHOD);
m.invoke(null);
System.exit(1);
}

}

Is it better to use local variables or chain methods inline?

Not chaining Methods :

ADV

  1. Enhances readability.

  2. Gives an opportunity for re-usage.

  3. Pin pointing exceptions (if any) becomes easier.

  4. Debugging becomes easier, i.e. setting breakpoints on specific invocation is easy.

DisADV

  1. Increases length( I wont say size :) ) of code.

  2. IDE warnings (if any).

Chaining Methods

ADV

  1. Reduces the need for creating multiple temp. variables.

  2. Is a syntactic sugar

  3. Reduces the number of lines to be written.

DisADV

  1. Reduces readability of code.

  2. Commenting becomes difficult (if any) for particular methods called.

  3. Debugging the whole chain of invocation becomes very difficult.

When to create a local variable and when to call an objects method?

You basically have two questions,

1) Is there a performance difference between the two?

Ans - It depends. It mainly depends how heavy your isValid() method is. If your method is doing some heavy computation to check the validity of the object and then give you a result, then obviously it is better to call this method once and then re-use it.

Suppose your method takes 1ms to compute the validity and return you a result, then 3 calls would take 3ms. But you could make a single call and re-use the value and save 2ms.

But if the method isValid() is very simple in terms of computation, then there is no performance difference between the two.

2) Is there a coding standard which states that if a method needs to be called more than once then a local variable should be created?

Ans - This is no hard-and-fast rule, but it is always cleaner to call the method once, grab its value and store it in a variable and then re-use it anytime you want.

But keep in mind, that if the isValid() methods result changes with time, then you need to call it multiple time. Suppose, you call it the first time and it gives you true, but you call it after 1 second and it gives you false, then in that case you CANNOT store the value and re-use it as the value changes. You need to call it multiple times.

Duplicate method call VS local variable

Depends on how expensive it is to call getLocalVariable(). For this particular example this seems relatively inexpensive because it's a simple getter, so no harm.

However, imagine that the getLocalVariable() takes 30 seconds to return, then the first example would be much more preferred.

Java coding style, local variables vs repeated method calls

Yeah the first one is definitely better. I would never go for the second method.
But you should think of using polymorphism more. Relying on instanceof so heavyly is not good OO design.



Related Topics



Leave a reply



Submit