プログラムdeタマゴ

nodamushiの著作物は、文章、画像、プログラムにかかわらず全てUnlicenseです

ディスられてた

ので、ディスりかえす。
かなり前の記事だが、
 
Java ? コンパイラの演算最適化
 
という記事で、シフト演算とビット演算調べてみたけど、大差ないじゃないか!といわれたので、馬鹿じゃねーのディスっておきます。(私の方の記事
 

public class Foo {

    public static void main(String[] args) {

        long normal = processByNormal();

        long shift = processByShift();

        System.out.println("Normal:" + normal + "ms");

        System.out.println("Shift:" + shift + "ms");

    }



    private static long processByNormal() {

        long start = System.currentTimeMillis();

        for (int i = 0; i < 100000; i++) {

            System.out.println(i / 2);

        }

        return System.currentTimeMillis() - start;

    }



    private static long processByShift() {

        long start = System.currentTimeMillis();

        for (int i = 0; i < 100000; i++) {

            System.out.println(i >> 1);

        }

        return System.currentTimeMillis() - start;

    }

}

10万回を対象にした実行結果
Normal:2828msShift:4641ms
シフト演算の方が遅いんですが…なぜ?何か間違えてますか?
 
 
………もう分かったよね?何間違ってるのか。
 
System.out.printlnは比較したい計算のウン千倍重たいからね。ていうか、System.out.printlnは同じ時間で実行できるとは限りませんから。
 
少なくともこの程度で私にディスろうなどとは3ヶ月早い!
あと、printの処理は渡された値が直接そのタイミングで表示される訳じゃない。
いったんバッファーにためておいて、ある程度たまってから出力されるって事も知っておこうね。デバッグ作業とかでSystem.out.printlnでやろうとするときとか重要よ、この知識。
 
確かに全ての環境で10倍近く差が出るとは限らないが、圧倒的に割り算よりシフト演算が軽いのは自分で計算機設計して作ってみたら自明のこと。
 
 
さて、該当ソースの部分をt=i/2;とt=i<<1;(tはループその外で用意しておく)と、して実行してみよう。
 
Normal:0ms
Shift:0ms
 
はい、こんなんじゃ全く比較にならないね。上で表示された時間のほとんどはprintlnで使った時間だ。
私は確か10億回ぐらい回した記憶があるよ。
 
あと、JVMが起動してからしばらくは不安定だから、しばらく待機させてから測定しないと意味ないよ。
 
まだ付け加えるなら、最初はループ部分のバイトコードをネイティブコードにコンパイルするから1回どっちも呼び出しておいてから測定しようね。
 
 
以上。
 
あと、ビット演算は読みにくいから使わないって言うのは基本的には同意するよ。
でも、私の作ってるのは速度が命なんだ。