Java : メソッド呼び出しの効率調査

ばかばかしいと言われようが、無駄だと言われようが、納得いくまで調査するのが信条ですから。それに、効果がないことが分かるというのも、有意な結果です。
1.デフォルトコンストラクタと普通のコンストラク

public final class A {
  String s0;
  String s1;
  A(String s0, String s1) {
    this.s0 = s0;
    this.s1 = s1;
  }
}
public final class B {
  String s0;
  String s1;
}
public final class Main {
  public static void main(String[] args) {
    int l = Integer.parseInt(args[0]);
    int s = 0;
    if(args[1].equals("A")){
      for (int i=0; i<l; ++i) {
        A a = new A("a","b");
        s += a.s0.length();
      }
    }else{
      for (int i=0; i<l; ++i) {
        B b = new B();
        b.s0 = "a";
        b.s1 = "b";
        s += b.s0.length();
      }
    }
    System.out.println(s);
  }
}

結果は、変化なし。

$ time java Main 100000000 A
100000000

real    0m11.545s
user    0m0.010s
sys     0m0.050s

$ time java Main 100000000 B
100000000

real    0m11.582s
user    0m0.010s
sys     0m0.050s

$ time java Main 300000000 A
300000000

real    0m33.765s
user    0m0.020s
sys     0m0.030s

$ time java Main 300000000 B
300000000

real    0m33.556s
user    0m0.010s
sys     0m0.050s

2.抽象クラスとインターフェース

public interface AIntf {
  int get();
}
public abstract class ASuper {
  public abstract int get();
}
public class A extends ASuper implements AIntf {
  public int get() { return 1;}
}
public final class Main {
  public static void main(String[] args) {
    int l = Integer.parseInt(args[0]);
    int s = 0;
    if (args[1].equals("interface")) {
      AIntf a = new A();
      for (int i=0; i<l; ++i) {
        s += a.get();
      }
    }else{
      ASuper a = new A();
      for (int i=0; i<l; ++i) {
        s += a.get();
      }
    }
    System.out.println(s);
  }
}

結果は、抽象クラスの方が効率的らしい。

$ time java Main 200000000 interface
200000000

real    0m5.271s
user    0m0.030s
sys     0m0.030s

$ time java Main 200000000 super    
200000000

real    0m3.425s
user    0m0.010s
sys     0m0.040s

$ time java Main 200000000 interface
200000000

real    0m5.231s
user    0m0.010s
sys     0m0.050s

$ time java Main 200000000 super
200000000

real    0m3.423s
user    0m0.010s
sys     0m0.040s

3.ExceptionとRuntimeException

public final class Main {
  static int a(int i) throws Exception {
    if (i<0) {
      throw new Exception();
    }else if(i==0) {
      return 1;
    }else{
      return a(i-1);
    }
  }
  
  static int b(int i) {
    if (i<0) {
      throw new RuntimeException();
    }else if(i==0) {
      return 1;
    }else{
      return b(i-1);
    }
  }
  
  static int c(int i) {
    if (i<0) {
      return -1;
    }else if(i==0) {
      return 1;
    }else{
      return c(i-1);
    }
  }
  
  public static void main(String[] args) {
    int l = Integer.parseInt(args[0]);
    int s = 0;
    if (args[1].equals("exception")) {
      try{
        for (int i=0; i<l; ++i) {
          s += a(10);
        }
      }catch(Exception e){}
    }else if (args[1].equals("runtimeexception")){
      try{
        for (int i=0; i<l; ++i) {
          s += b(10);
        }
      }catch(RuntimeException e){}
    }else{
      try{
        for (int i=0; i<l; ++i) {
          s += c(10);
        }
      }catch(Exception e){}
    }
    System.out.println(s);
  }
}

結果は、差はないといえそう。

$ time java Main 30000000 exception
30000000

real    0m6.800s
user    0m0.010s
sys     0m0.040s

$ time java Main 30000000 runtimeexception
30000000

real    0m6.744s
user    0m0.030s
sys     0m0.030s

$ time java Main 30000000 none
30000000

real    0m7.163s
user    0m0.020s
sys     0m0.030s