Are Java static calls more or less expensive than

2019-01-06 10:37发布

Is there any performance benefit one way or another? Is it compiler/VM specific? I am using Hotspot.

12条回答
ら.Afraid
2楼-- · 2019-01-06 10:42

In theory, less expensive.

Static initialization is going to be done even if you create an instance of the object, whereas static methods will not do any initialization normally done in a constructor.

However, I haven't tested this.

查看更多
迷人小祖宗
3楼-- · 2019-01-06 10:44

There might be a difference, and it might go either way for any particular piece of code, and it might change with even a minor release of the JVM.

This is most definitely part of the 97% of small efficiencies that you should forget about.

查看更多
闹够了就滚
4楼-- · 2019-01-06 10:46

As Jon notes, static methods can't be overridden, so simply invoking a static method may be -- on a sufficiently naive Java runtime -- faster than invoking an instance method.

But then, even assuming you're at the point where you care about messing up your design to save a few nanoseconds, that just brings up another question: will you need method overriding yourself? If you change your code around to make an instance method into a static method to save a nanosecond here and there, and then turn around and implement your own dispatcher on top of that, yours is almost certainly going to be less efficient than the one built into your Java runtime already.

查看更多
萌系小妹纸
5楼-- · 2019-01-06 10:49

For the decision if a method should be static, the performance aspect should be irrelevant. If you have a performance problem, making lots of methods static isn't going to save the day. That said, static methods are almost certainly not slower than any instance method, in most cases marginally faster:

1.) Static methods are not polymorphic, so the JVM has less decisions to make to find the actual code to execute. This is a moot point in the Age of Hotspot, since Hotspot will optimize instance method calls that have only one implementation site, so they will perform the same.

2.) Another subtle difference is that static methods obviously have no "this" reference. This results in a stack frame one slot smaller than that of an instance method with the same signature and body ("this" is put in slot 0 of the local variables on the bytecode level, whereas for static methods slot 0 is used for the first parameter of the method).

查看更多
Juvenile、少年°
6楼-- · 2019-01-06 10:50

7 years later...

I don't have a huge degree of confidence in the results that Mike Nakis found because they don't address some common issues relating to Hotspot optimisations. I've instrumented benchmarks using JMH and found the overhead of an instance method to be about 0.75% on my machine vs a static call. Given that low overhead I think except in the most latency sensitive operations it's arguably not the biggest concern in an applications design. The summary results from my JMH benchmark are as follows;

java -jar target/benchmark.jar

# -- snip --

Benchmark                        Mode  Cnt          Score         Error  Units
MyBenchmark.testInstanceMethod  thrpt  200  414036562.933 ± 2198178.163  ops/s
MyBenchmark.testStaticMethod    thrpt  200  417194553.496 ± 1055872.594  ops/s

You can look at the code here on Github;

https://github.com/nfisher/svsi

The benchmark itself is pretty simple but aims to minimise dead code elimination and constant folding. There are possibly other optimisations that I've missed/overlooked and these results are likely to vary per JVM release and OS.

package ca.junctionbox.svsi;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.infra.Blackhole;

class InstanceSum {
    public int sum(final int a, final int b) {
        return a + b;
    }
}

class StaticSum {
    public static int sum(final int a, final int b) {
        return a + b;
    }
}

public class MyBenchmark {
    private static final InstanceSum impl = new InstanceSum();

    @State(Scope.Thread)
    public static class Input {
        public int a = 1;
        public int b = 2;
    }

    @Benchmark
    public void testStaticMethod(Input i, Blackhole blackhole) {
        int sum = StaticSum.sum(i.a, i.b);
        blackhole.consume(sum);
    }

    @Benchmark
    public void testInstanceMethod(Input i, Blackhole blackhole) {
        int sum = impl.sum(i.a, i.b);
        blackhole.consume(sum);
    }
}
查看更多
Juvenile、少年°
7楼-- · 2019-01-06 10:50

It is unbelievably unlikely that any difference in the performance of static versus non-static calls is making a difference in your application. Remember that "premature optimization is the root of all evil".

查看更多
登录 后发表回答