「繰り返し処理中のオブジェクトの生成は最小限にする」
- C_CTR009 繰り返し処理中のオブジェクトの生成は最小限にする
繰り返し回数の多いループの内部でオブジェクトを生成することは、生成に時間がかかるため回数によっては、大きなパフォーマンス低下につながることがあります。これを回避するには、ループ外でインスタンス作成しそれを再利用します。
http://74.125.153.132/search?q=cache:nAtQuR5h4GYJ:www.objectclub.jp/community/codingstandard/JavaCodingStandard2004.pdf+java+%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E8%A6%8F%E7%B4%84+%E9%9B%BB%E9%80%9A&cd=1&hl=ja&ct=clnk&gl=jp&lr=lang_ja&client=firefox-a
public class Hoge { public static void main(String[] args) { int j = 100000000; { long start = System.currentTimeMillis(); StringBuffer s = new StringBuffer(); for (int i = 0; i < j; i++) { s.append("hoge"); s.setLength(0); } System.out.println("1:"+(System.currentTimeMillis() - start)); } { long start = System.currentTimeMillis(); for (int i = 0; i < j; i++) { StringBuffer s = new StringBuffer(); s.append("hoge"); } System.out.println("2:"+(System.currentTimeMillis() - start)); } } }
1:11786 2:7800
new StringBuffer()ではインスタンス変数valueにchar配列を定義するだけだが、setLength(int newLength)では引数チェック、バッファとの大小チェック、文字との大小チェックを経て、ようやく長さが0になる。たぶんこの違い。
StringBufferのバッファ初期値は16で、16文字を超えるとバッファを2倍に拡張するしつつ値をコピーするので、appendする文字が20文字とかだったら、もしかして後者の方が早いかもしれない。使い回すオブジェクトのバッファは、既に拡張されているので。ただ、その見込みがあるのであれば、new時に容量を指定する方を選ぶべきだったり。
(追記:それでも、文字が多いと前者の方が少し早い様子。んー、この差ってどこからくるんだろか。)
(さらに:いや、バッファの初期値が実際にappendされる数に近ければ、後者の方が早い。"hoge"を25個appendするなら、バッファ初期値は100など。ま、あれだ。clearメソッドがないオブジェクトを使い回すなってことかw)
パフォーマンスに関する意見は短命なものです。パフォーマンスに関する助言に出くわしたときは、それを事実として受け入れる前に、それが時代遅れではないかという疑問を持ってください。
(...)まず最初に、変更によって本当にアプリケーションのパフォーマンスが向上するのか、そして、そもそもそのアプリケーションにパフォーマンスの改善が必要なのか自問自答してください。
Javaの理論と実践: パフォーマンスの都市伝説
もっともこの問題は、時代的なものはあんまり関係なさそうだけどね。