3

重複の可能性:
ループの最適化

string の文字をループしたいとしましょうs。次のコードは多かれ少なかれデフォルトだと思います。

for( int i = 0; i < s.length(); i++ ) {
    doSomethingWith( s.charAt( i ) );
}

質問 #1: 以下のようなことが頻繁に見られるのはなぜですか?

final int length = s.length();
for( int i = 0; i < length; i++ ) {
    doSomethingWith( s.charAt( i ) );
}

不等式はすべての反復で評価されるため、一見これは妥当に思えます。ただし、文字列は不変であるため、とにかく VM がこれを最適化することを期待します。何かご意見は?そして、変更可能な構造 (他のスレッドから参照されていない構造) を反復処理するとどうなるでしょうか? length()O(1) での実行が保証されていない場合はどうなるでしょうか。

質問 #2: 一部の人々は、コードを高速化する++iために置き換えることを考えているようです。i++彼らは正しいですか?繰り返しますが、これは私が期待するものではありませんが、よくわかりません。

時期尚早に最適化してはならないことは誰もが知っています。同時に、ほとんど費用をかけずにわずかに高速なコードを作成できるとしたら、そうしないのは愚かなことです。もちろん、両方の「最適化」が可読性を損なうと主張することもできますが、私の意見では、損傷は非常に小さいため、特定の状況では正当化されます。

パフォーマンスの違いを測定しようとしましたが、決定的な結果を得るのは困難です。これで特定のアプリケーションについては解決するはずですが、ここで洞察と一般的な回答を目指しています。

(HotSpot VM を念頭に置いてこれを書きましたが、モバイル デバイスなどの他のプラットフォームを検討することも興味深いかもしれません。)

4

2 に答える 2

5

質問 #1: 以下のようなことが頻繁に見られるのはなぜですか?

最初の例は時期尚早の最適化です。人々がそうする理由は、多くの場合、実際のボトルネックがどこにあるかを確認するためにコードをプロファイリングせず、代わりに単に推測しようとするためです。

length() が O(1) で実行されることが保証されていない場合はどうなるでしょうか?

次に、この最適化を行う方が理にかなっています。長さの計算が高価な操作であり、値が変わらないことがわかっている場合は、一度計算して結果を保存すると、パフォーマンスが向上する可能性があります。

質問 #2: 一部の人々は、i++ を ++i に置き換えるとコードが高速になると考えているようです。彼らは正しいですか?繰り返しますが、これは私が期待するものではありませんが、よくわかりません。

彼らは正しくありません。彼らの主張はi++、変数の一時的なコピーを作成する必要があるのに対し、作成++iしないというものです。これは、コンパイラの最適化が苦手だったはるか昔の C または C++ で当てはまったことです。Java には当てはまりません。

于 2012-08-24T19:35:29.403 に答える
3

At first sight this seems reasonable since the inequality is evaluated on every iteration. I would however expect the VM to optimize this anyway, since strings are immutable.

The compiler optimizes this. Doing it like i < s.length(); is fine.

Some people seem to think substituting ++i for i++ speeds up the code.

It doesn't, unless you're assigning something to the return value of ++i

于 2012-08-24T19:35:41.963 に答える