はじめに
- みなさんコーディングをしてきて、今までに何回ifを書いてきましたか?笑
- 何万回と書いていても、たまにswitchを使うかifを使うか悩みますよね??(僕は悩むことがあります)
今の僕の選択基準
- if文を選ぶとき:&&とか||したいとき
- switchするとき:選択肢がいっぱいあるとき
- switchするまでもないとき:三項演算子
- あとは悩んだら感覚
- てな感じで選んでたわけなんですが、ある日僕は思いました
どっちでもかけるときってどっちがパフォーマンス出るんだろう?
- 気になったら計測すればいいんじゃね?と思い立ちます
- いざ、実行!
用意したもの
- Java1.8
- IntelliJ IDEA
目次(目次を書いてる時点でやる想定のもの)
- 100回くらいのループで分岐を走らせる
- 100回で性能差が出なかったら、桁数を1つずつ増やしていく
- ある程度満足したら、条件を増やしていく
- 条件増やすのにも満足したら、文字列と数字のパターンをやる
- こんな感じでやります
実践
100回くらいのループで分岐を走らせる
- 実行したコードは下記
CheckPerformance.java
import java.util.stream.IntStream;
public class CheckPerformance {
public static void main(String[] args) {
Long start = System.currentTimeMillis();
// if実行分
IntStream.rangeClosed(0, 100).forEach(i -> {
if (i % 2 == 0) {
System.out.println("偶数です");
} else if (i % 2 == 1) {
System.out.println("奇数です");
} else {
System.out.println("その他です");
}
});
// switch実行分
IntStream.rangeClosed(0, 100).forEach(i -> {
switch (i % 2) {
case 0:
System.out.println("偶数です");
break;
case 1:
System.out.println("奇数です");
break;
default:
System.out.println("その他です");
break;
}
});
Long end = System.currentTimeMillis();
System.out.println(end - start + "ms");
}
}
- 実行結果は下記です
X回目 | ifの実行秒数 | switchの実行秒数 |
---|---|---|
1回目 | 7ms | 12ms |
2回目 | 15ms | 10ms |
3回目 | 13ms | 12ms |
4回目 | 8ms | 15ms |
5回目 | 10ms | 10ms |
検証
- 他にも何回か実行したが、運ゲーみたいになったので100回では性能差を検証するのは難しいと判断
- 要するに誤差でしかない
1,000回のループで分岐を走らせる
- ソースは省略
- 実行結果は下記です
X回目 | ifの実行秒数 | switchの実行秒数 |
---|---|---|
1回目 | 36ms | 39ms |
2回目 | 33ms | 35ms |
3回目 | 31ms | 28ms |
4回目 | 38ms | 39ms |
5回目 | 38ms | 34ms |
検証
- うーん、1,000回でも性能差を検証するのは微妙
- ここでもまだ、誤差の範疇な気がする
10,000回のループで分岐を走らせる
- ソースは(ry
- 実行結果は下記です
X回目 | ifの実行秒数 | switchの実行秒数 |
---|---|---|
1回目 | 133ms | 119ms |
2回目 | 147ms | 136ms |
3回目 | 116ms | 121ms |
4回目 | 135ms | 130ms |
5回目 | 128ms | 136ms |
検証
- うーん、10,000回でも...(ry
100,000回のループで分岐を走らせる
- ソースは(ry
- 実行結果は下記です
X回目 | ifの実行秒数 | switchの実行秒数 |
---|---|---|
1回目 | 903ms | 917ms |
2回目 | 947ms | 885ms |
3回目 | 1012ms | 964ms |
4回目 | 1109ms | 947ms |
5回目 | 943ms | 884ms |
検証
- 100,000回でちょっとだけ性能差がでた気がします
- switchが1秒超えたのが0回だったのに対して、ifは2回ありますね。
- とはいえ、誤差っちゃ誤差なのかもしれないし、平均値だけみるとswitchの方が早いのかも?って仮説はたちました
- でも、ちょっと不安なのでもう1桁だけ増やして実行しておきます
1,000,000回のループで分岐を走らせる
- s..(ry
- 実行結果は下記です
X回目 | ifの実行秒数 | switchの実行秒数 |
---|---|---|
1回目 | 6366ms | 6339ms |
2回目 | 6410ms | 6396ms |
3回目 | 6794ms | 6298ms |
4回目 | 6730ms | 6248ms |
5回目 | 6823ms | 6495ms |
検証
- 1,000,000回での性能差はご覧の通りです
- switchの方が速度にばらつきが無かった気がするのと、やっぱり若干ですが早いという結果に
- とはいえ、100万件やってようやくこれだけしか性能差が出ないんで、普段使いで性能差を意識することはなかなかなさそうですかね
分岐を増やしていく
- では、ある程度満足したので分岐を増やしていきます
- ここからは100件でやってもあまり意味がないことがわかったので100万件で実施していきます
まずは分岐を3つにする
- ソースは省略します
- 実行結果は下記です
X回目 | ifの実行秒数 | switchの実行秒数 |
---|---|---|
1回目 | 6348ms | 6476ms |
2回目 | 6751ms | 6354ms |
3回目 | 6461ms | 6324ms |
4回目 | 6500ms | 6411ms |
5回目 | 6537ms | 6646ms |
検証
- 分岐3回での性能差はご覧の通りです
- 平均値でみたときにはswitchの方が、やっぱり若干ですが早いですかね
- とはいえ、誤差なのかもしれないので分岐を増やします
分岐を5つにする
- 5つにしたのは計算の都合上と気分です
- 実行結果は下記です
X回目 | ifの実行秒数 | switchの実行秒数 |
---|---|---|
1回目 | 6528ms | 6279ms |
2回目 | 6452ms | 6507ms |
3回目 | 6661ms | 6599ms |
4回目 | 6501ms | 6589ms |
5回目 | 6608ms | 6322ms |
検証
- 分岐5回での性能差はご覧の通りです
- うーん誤差の範囲内ですかね。
結論
ifとswitchは性能差はほとんどない!
- タイトルで釣っておいてあれなんですが、僕なりの結論です
- 100万件しか実行してないのですが、もっと増えれば変わる可能性はあるかもなのは重々承知してます
- とはいえ、分岐の数や処理件数でifとswitchでパフォーマンスが顕著に変わることはないっぽいので、その時々に合わせて読みやすくなる実装を選択するという判断が正しい気がします
- 何かおかしいだろとか、もっとこんな検証した方がいい等々あればコメントでも編集リクエストでもください!
追記
- コメントにてprintlnが重すぎるのでというご指摘をいただいたので、処理を直してみました
Main.java
import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
long start = System.currentTimeMillis();
IntStream.rangeClosed(0, 10000000).forEach(
num -> {
if (num % 2 == 0) {
int num2 = 2;
} else if (num % 2 == 1){
int num3 = 2;
} else {
int num4 = 2;
}
}
);
IntStream.rangeClosed(0, 10000000).forEach(
num -> {
switch (num % 2) {
case 0:
int num2 = 2;
break;
case 1:
int num3 = 2;
break;
default:
int num4 = 2;
break;
}
}
);
long end = System.currentTimeMillis();
System.out.println((end - start) + "ms");
}
}
- I/Oの処理が重いのでとりあえずfor文の中で変数宣言するだけにしてみました
- もっといけてる方法あったらおしえてください
実行結果
X回目 | ifの実行秒数 | switchの実行秒数 |
---|---|---|
1回目 | 79ms | 70ms |
2回目 | 81ms | 64ms |
3回目 | 90ms | 62ms |
4回目 | 86ms | 67ms |
5回目 | 83ms | 63ms |
- 1000万件回して差分が20msくらいは性能差が出ましたが、やはりほとんどないという結論で問題ないのかと。
- byteコードの検証は後日します!