代码之家  ›  专栏  ›  技术社区  ›  PeterMmm

Java的varargs性能

  •  13
  • PeterMmm  · 技术社区  · 16 年前

    我来这里是为了检查Java的vararg性能。

    我编写了以下测试代码:

    public class T {
    
        public static void main(String[] args) {
    
            int n = 100000000;
            String s1 = new String("");
            String s2 = new String("");
            String s3 = new String("");
            String s4 = new String("");
            String s5 = new String("");
    
            long t = System.currentTimeMillis();
            for (int i = 0; i < n; i++) {
                foo();
            }
            System.err.println(System.currentTimeMillis() - t);
    
    
            t = System.currentTimeMillis();
            for (int i = 0; i < n; i++) {
                baz(s1, s2, s3, s4, s5);
            }
            System.err.println(System.currentTimeMillis() - t);
    
            t = System.currentTimeMillis();
            for (int i = 0; i < n; i++) {
                bar(s1, s2, s3, s4, s5);
            }
            System.err.println(System.currentTimeMillis() - t);
    
        }
    
        static void foo() {
        }
    
        static void bar(String a1, String a2, String a3, String a4, String a5) {
        }
    
        static void baz(String... a) {
        }
    }
    

    78
    4696
    78
    

    似乎把变量传递给方法是免费的?!很好!

    0
    62
    0
    

    更新

    t = System.currentTimeMillis();
    for (int i = 0; i < n; i++) {
        baz(s1);
    }
    System.err.println(System.currentTimeMillis() - t);
    

    而这个单参数版本仍然慢了30倍。可能在场景后面有一个ArrayList.toArray()?

    因此,请注意代码中不需要varags方法,并进行重构以固定长度。这可能是一个性能提升。

    4 回复  |  直到 16 年前
        1
  •  21
  •   Konrad Garus    16 年前

    静态参数列表与数组完全不同。当您以这种方式传递它们时,编译器会为引用保留空间,并在调用方法时填充它们。

    String[] String...

        2
  •  9
  •   Alexander Ryzhov    13 年前

    69
    69
    311
    

    但是,我不会贸然下结论,因为这个基准有几个缺陷:函数中没有使用参数;函数什么都不做;参数具有相同的值。JIT可以轻松地优化此代码和内联函数调用。我修改了您的示例以解决上述明显的问题,并得到以下结果:

    627
    7470
    7844
    

    结论是: 不要犹豫使用varargs . 如果您的函数是琐碎的,那么它的调用将由JIT内联,如果不是,那么varargs的开销可能可以忽略不计。

        3
  •  1
  •   Olivier Croisier    16 年前

        4
  •  0
  •   Olivier Girardot    16 年前

    如前所述,使用var args时会维护数组。。。,

    您还应该尝试查看在每个方法的参数中添加“final”的影响

    我个人的成绩比2250有所提高->阵列2234 ms。

        5
  •  0
  •   clankill3r    6 年前

    我重构了一些代码。我用 int 而不是现在 String

    我对这些方法做了一些事情,也反对编译器优化。

    public class Test {
    
    
        static int n = 100_000_000;
        static int[] all_string = new int[n*1*5];
        static int all_strings_index = 0;
    
    
    
        public static void main(String[] args) {
    
            while(true) {
        
                all_strings_index = 0;
        
                int s1 = (int) System.nanoTime();
                int s2 = (int) System.nanoTime();
                int s3 = (int) System.nanoTime();
                int s4 = (int) System.nanoTime();
                int s5 = (int) System.nanoTime();
        
                long t = System.currentTimeMillis();
        
        
                t = System.currentTimeMillis();
                for (int i = 0; i < n; i++) {
                    var(s1, s2, s3, s4, s5);
                }
                System.err.println("varargs    "+(System.currentTimeMillis() - t));
        
                all_strings_index = 0;
        
                t = System.currentTimeMillis();
                for (int i = 0; i < n; i++) {
                    par(s1, s2, s3, s4, s5);
                }
                System.err.println("parameters "+(System.currentTimeMillis() - t));
        
        
                all_strings_index = 0;
        
                int[] arr = new int[] {s1, s2, s3, s4, s5};
        
                t = System.currentTimeMillis();
                for (int i = 0; i < n; i++) {
                    var2(arr);
                }
                System.err.println("array      "+(System.currentTimeMillis() - t));
                System.err.println();
        
            }
    
        }
    
        static void par(int a1, int a2, int a3, int a4, int a5) {
            all_string[all_strings_index++] = a1;
            all_string[all_strings_index++] = a2;
            all_string[all_strings_index++] = a3;
            all_string[all_strings_index++] = a4;
            all_string[all_strings_index++] = a5;
        }
    
        static void var(int... a) {
            for (int s : a) {
                all_string[all_strings_index++] = s;
            }
        }
    
        static void var2(int[] a) {
            for (int s : a) {
                all_string[all_strings_index++] = s;
            }
        }
    }
    
    varargs    981
    parameters 415
    array      687
    
    varargs    962
    parameters 434
    array      411
    
    varargs    975
    parameters 469
    array      439
    
    varargs    983
    parameters 462
    array      447
    
    varargs    999
    parameters 470
    array      439
    
    varargs    1018
    parameters 475
    array      455
    
    varargs    1014
    parameters 467
    array      440