Q. なぜ”B”と表示するのは”#”と表示するよりも著しく遅いのか?

質問 なぜ”B”と表示するのは”#”と表示するよりも著しく遅いのでしょうか?

1000 x 1000のマトリックスを2つ作りました。

1つ目のマトリックス:O#
2つ目のマトリックス:OB

次に示すコードを使うと、1つ目のマトリックスは出力が完了するまでに8.52秒かかりました。

Random r = new Random();
for (int i = 0; i < 1000; i++) {
    for (int j = 0; j < 1000; j++) {
        if(r.nextInt(4) == 0) {
            System.out.print("O");
        } else {
            System.out.print("#");
        }
    }

   System.out.println("");
 }

以下のコードで、2つ目のマトリックスは出力が完了するまでに259.152秒かかりました。

Random r = new Random();
for (int i = 0; i < 1000; i++) {
    for (int j = 0; j < 1000; j++) {
        if(r.nextInt(4) == 0) {
            System.out.print("O");
        } else {
            System.out.print("B"); //only line changed
        }
    }

    System.out.println("");
}

これほど実行時間に著しい差異が生じたのは、なぜでしょうか?


コメントで示されている通り、System.out.print("#");だけの表示ならば、かかる時間は7.8871秒なのですが、System.out.print("B");を含むとstill printing...となってしまいます。

自分の環境では問題がなかったと指摘する方々もいらっしゃるように、この2つのコードを試しにIdeone.comで実行してみたところ、同じ速さで実行できました。

テスト条件は次の通りです。

  • 実行環境はNetBeans 7.2でのコンソール出力
  • 計測に使用したのはSystem.nanoTime()

asked by Kuba Spatny

Answer(s)

Answer 1

まったくの推測なのですが、使っている端末が、文字単位の折り返しではなくワードラップを行っており、Bは単語を構成する文字として、#は単語を構成しない文字として扱っているのではないでしょうか。つまり、行末に達して、折り返すべき位置を探す際、#であればほぼ即時に適切にその位置で折り返すことができます。それに比べると、Bの方が折り返し位置を探す時間は長くなりますし、折り返すべきテキストも多くなるかもしれません(これは端末によっては、コストの高い処理となる可能性があります。例えば、バックスペースを出力したあと、折り返されている文字の部分を上書きするためのスペースを出力するかもしれません)。

ただし、上記はあくまでも推測です。

community wiki by T.J. Crowder

Answer 2

EclipseとNetBeans 8.0.2の両環境でテストしてみました。いずれもJavaのバージョンは1.8で、計測にはSystem.nanoTime()を使いました。

Eclipse

どちらの場合も同じ時間がかかりました。1.564秒ぐらいです。

NetBeans

  • “#”を使用:1.536秒
  • “B”を使用:44.164秒

つまり、NetBeansではコンソール表示のパフォーマンスが悪いようです。

さらに調べた結果、NetBeansでは行折り返しが最大バッファで行われることが問題であると分かりました(これはSystem.out.printlnコマンドに限りません)。以下のコードで確認できます。

for (int i = 0; i < 1000; i++) {
    long t1 = System.nanoTime();
    System.out.print("BBB......BBB"); \\<-contain 1000 "B"
    long t2 = System.nanoTime();
    System.out.println(t2-t1);
    System.out.println("");
}

試した結果、かかった時間は例外を除いてどの繰り返しでも1ミリ秒未満となり、5回目ごとの繰り返しの際に限って225ミリ秒ぐらいかかりました。次のような状況です(単位はナノ秒)。

BBB...31744
BBB...31744
BBB...31744
BBB...31744
BBB...226365807
BBB...31744
BBB...31744
BBB...31744
BBB...31744
BBB...226365807
.
.
.

以下、続いていきます。

まとめ

  1. Eclipseでは”B”でも問題なく動作する。
  2. NetBeansでは行折り返しが問題となるが、解決策はあるはず(Bの後ろにスペースを入れて”B “としなくても、Eclipseでは同じ問題が起きていないため)。

answered by Roy Shmuli