Performance of variable argument methods in Java

前端 未结 6 1149
小鲜肉
小鲜肉 2020-12-19 20:42

I have this question about the performance of a method in Java with a variable number of parameters.

Say I have the following 2 alternatives:

public          


        
相关标签:
6条回答
  • 2020-12-19 20:48

    Heard about the two optimisation rules:

    • Don't optimize
    • (For experts only!) Don't optimize yet

    In other words this is nothing you should care about from the performance point of view.

    0 讨论(0)
  • 2020-12-19 20:52

    I had the same question, and turned to experimentation.

    public class ArgTest {
    
      int summation(int a, int b, int c, int d, int e, int f) {
        return a + b + c + d + e + f;
      }
    
      int summationVArgs(int... args) {
        int sum = 0;
        for (int arg : args) {
          sum += arg;
        }
        return sum;
      }
    
      final static public int META_ITERATIONS = 200;
      final static public int ITERATIONS = 1000000;
    
      static public void main(String[] args) {
        final ArgTest at = new ArgTest();
        for (int loop = 0; loop < META_ITERATIONS; loop++) {
          int sum = 0;
          final long fixedStart = System.currentTimeMillis();
          for (int i = 0; i < ITERATIONS; i++) {
            sum += at.summation(2312, 45569, -9816, 19122, 4991, 901776);
          }
          final long fixedEnd = System.currentTimeMillis();
          final long vargStart = fixedEnd;
          for (int i = 0; i < ITERATIONS; i++) {
            sum += at.summationVArgs(2312, 45569, -9816, 19122, 4991, 901776);
          }
          final long vargEnd = System.currentTimeMillis();
          System.out.printf("%03d:%d Fixed-Args: %d ms\n", loop+1, ITERATIONS, fixedEnd - fixedStart);
          System.out.printf("%03d:%d Vargs-Args: %d ms\n", loop+1, ITERATIONS, vargEnd - vargStart);
        }
        System.exit(0);
      }
    
    }
    

    If you run this code on a modern JVM (here 1.8.0_20), you will see that the variable number of arguments cause overhead in performance and possible in memory consumption as well.

    I'll only post the first 25 runs:

    001:1000000 Fixed-Args: 16 ms
    001:1000000 Vargs-Args: 45 ms
    002:1000000 Fixed-Args: 13 ms
    002:1000000 Vargs-Args: 32 ms
    003:1000000 Fixed-Args: 0 ms
    003:1000000 Vargs-Args: 27 ms
    004:1000000 Fixed-Args: 0 ms
    004:1000000 Vargs-Args: 22 ms
    005:1000000 Fixed-Args: 0 ms
    005:1000000 Vargs-Args: 38 ms
    006:1000000 Fixed-Args: 0 ms
    006:1000000 Vargs-Args: 11 ms
    007:1000000 Fixed-Args: 0 ms
    007:1000000 Vargs-Args: 17 ms
    008:1000000 Fixed-Args: 0 ms
    008:1000000 Vargs-Args: 40 ms
    009:1000000 Fixed-Args: 0 ms
    009:1000000 Vargs-Args: 89 ms
    010:1000000 Fixed-Args: 0 ms
    010:1000000 Vargs-Args: 21 ms
    011:1000000 Fixed-Args: 0 ms
    011:1000000 Vargs-Args: 16 ms
    012:1000000 Fixed-Args: 0 ms
    012:1000000 Vargs-Args: 26 ms
    013:1000000 Fixed-Args: 0 ms
    013:1000000 Vargs-Args: 7 ms
    014:1000000 Fixed-Args: 0 ms
    014:1000000 Vargs-Args: 7 ms
    015:1000000 Fixed-Args: 0 ms
    015:1000000 Vargs-Args: 6 ms
    016:1000000 Fixed-Args: 0 ms
    016:1000000 Vargs-Args: 141 ms
    017:1000000 Fixed-Args: 0 ms
    017:1000000 Vargs-Args: 139 ms
    018:1000000 Fixed-Args: 0 ms
    018:1000000 Vargs-Args: 106 ms
    019:1000000 Fixed-Args: 0 ms
    019:1000000 Vargs-Args: 70 ms
    020:1000000 Fixed-Args: 0 ms
    020:1000000 Vargs-Args: 6 ms
    021:1000000 Fixed-Args: 0 ms
    021:1000000 Vargs-Args: 5 ms
    022:1000000 Fixed-Args: 0 ms
    022:1000000 Vargs-Args: 6 ms
    023:1000000 Fixed-Args: 0 ms
    023:1000000 Vargs-Args: 12 ms
    024:1000000 Fixed-Args: 0 ms
    024:1000000 Vargs-Args: 37 ms
    025:1000000 Fixed-Args: 0 ms
    025:1000000 Vargs-Args: 12 ms
    ...
    

    Even at the best of times, the Vargs-Args never dropped to 0ms.

    0 讨论(0)
  • 2020-12-19 20:52

    Come back when you have profiler output that says this is a problem. Until then, it's premature optimization.

    0 讨论(0)
  • 2020-12-19 20:52

    to @Canonical Chris

    I don't think problem at your test come from variable argument. The function sumationVArgs take more time to complete because of for loop.

    I created this function and added to the benchmark

    int summationVArgs2(int... args) {
            return args[0] + args[1] + args[2] + args[3] + args[4] + args[5];
        }
    

    and this is what I see:

    028:1000000 Fixed-Args: 0 ms
    028:1000000 Vargs-Args: 12 ms
    028:1000000 Vargs2-Args2: 0 ms
    

    The for loop in function "summationVArgs" is compiled to more operations than add function. It contains add operation to increase iterator, check operation to check condition and branch operation to loop and exit loop, and all of them execute once for each loop except branch opration to exit loop.

    Sorry for my bad English. I hop you can understand my English :)

    0 讨论(0)
  • 2020-12-19 21:10

    The compiler does next to no optimisation. The JVM can optimise code but the two methods won't perform anything like each other. If you have lines of code like isIn(i, 1,2,3,4,5,6,7,8,9 /* plus 40 more */) you have more than performance issues to worry about IMHO. I would worry about readability first.

    If you are worried about performance pass the arguments as a int[] which is reused.

    BTW The most efficient way to look up a large set of int values is to use a Set like TIntHashSet

    0 讨论(0)
  • 2020-12-19 21:11

    It will be the same as if you declared

     isIn(int i, int[] values) {
    

    However there will be some some small overhead in packaging the variables up when calling your method

    0 讨论(0)
提交回复
热议问题