JAVA豆知識
パフォーマンスにおける留意点
1.文字列の連結を行う場合は、StringBufferクラスを用いる
必要な文字列のサイズがわかる場合は、StringBufferクラスの
生成時にあらかじめ十分な容量を確保するようにする
必要な文字列のサイズがわかる場合は、StringBufferクラスの
生成時にあらかじめ十分な容量を確保するようにする
//Stringクラスによる文字連結 String str_x = "x"; String str_y = "y"
String str = str_x + str_y;
【内部処理】
String str = (new StringBuffer()).append(str_x).append(str_y).toString();
①StringBufferクラスの生成
②Stringクラスの生成(toString()メソッドによる)
③Stringクラス、StringBufferクラスが内部で保持しているchar型配列の生成
②Stringクラスの生成(toString()メソッドによる)
③Stringクラス、StringBufferクラスが内部で保持しているchar型配列の生成
無駄な内部処理を避ける為、StringBufferクラスを用いる
//StringBufferクラスによる文字連結 StringBuffer sb = new StringBuffer(); sb.append(str_x); sb.append(str_y); String str = sb.toString();
2.無駄なオブジェクトの生成を減らす
・冗長な初期化は行わないようにする
・必要なオブジェクトは必要な時点で初期化する
・ソースコードの途中で不要となった生成済みのオブジェクトは明示的に解放する
・繰り返し利用できたり、ほかの部分で利用可能な生成済みのオブジェクトは再利用する
・冗長な初期化は行わないようにする
・必要なオブジェクトは必要な時点で初期化する
・ソースコードの途中で不要となった生成済みのオブジェクトは明示的に解放する
・繰り返し利用できたり、ほかの部分で利用可能な生成済みのオブジェクトは再利用する
【詳細】
○Garbage Collector
java言語ではオブジェクトを一度生成したとき、その後使用されなくなったオブジェクトはGarbage Collector(GC)によって自動的に回収される。プログラム上であまり長い間使用しないオブジェクトを多数生成してしまった場合、GCが頻繁に動くために余計なコストが掛かってしまい、パフォーマンスに影響を与えてしまう。
○Garbage Collector
java言語ではオブジェクトを一度生成したとき、その後使用されなくなったオブジェクトはGarbage Collector(GC)によって自動的に回収される。プログラム上であまり長い間使用しないオブジェクトを多数生成してしまった場合、GCが頻繁に動くために余計なコストが掛かってしまい、パフォーマンスに影響を与えてしまう。
①オブジェクトの初期化を繰り返し行わない
public class TestOfNew { private final String TEST = new String(); public TestOfNew() { TEST = new String(); } }
当然ながら初期化の分の処理コストが増えるため、パフォーマンスが低下。
②オブジェクトの初期化は必要な時点で行う
TestObj obj = new TestObj(); if(hensu == 1){ obj.setXXX("XXX"); 処理・・・ } else { }
先頭部分で初期化したオブジェクトがその後のif分岐等により
使用されないまま処理が終了してしまうケース。
使用されないまま処理が終了してしまうケース。
- オブジェクトを生成すると処理コストが余計にかかる
- 初期化したオブジェクトの容量によっては、サーバのメモリを圧迫してしまい、パフォーマンスの低下を招く
- 一定期間使用されないと、GCがオブジェクトを破棄してメモリを解放するため、さらに余計なコストが掛かる
⇒オブジェクトの初期化は実際に必要となる時点で行う。
3.不要になった生成済みのオブジェクトは明示的にnullを代入して解放
オブジェクトを生成すれば、その分のメモリは消費されて サーバのメモリが圧迫される。そこで途中で必要がなくなった オブジェクトはできるだけすぐにGCによって回収してメモリを 解放したほうがメモリ使用量を抑制することができる。 そのため、開発者がプログラムロジック上で不要になった オブジェクトに対して明示的にnullを代入することによって、 GCが各オブジェクトがプログラム上で不要になったかどうかを 判断する際の有効な材料となる。 プログラム上で多数のオブジェクトを生成しているために Webアプリケーションサーバのメモリを圧迫しているシステムに 対してはパフォーマンス上の効果があると思われる。
4.コレクションクラスと配列
コレクションクラスを初期化するときには、使用するサイズを
適切に指定して動的なサイズの拡大を行わない。
コレクションクラスを初期化するときには、使用するサイズを
適切に指定して動的なサイズの拡大を行わない。
【詳細】
Vector・ArrayListクラスはデフォルトのコンストラクタを
使用して初期化するとサイズは10となる。
オブジェクトの追加によって生成時に指定したサイズを超えて
しまった場合は、自動的に生成したコレクションクラスオブジェクト
のサイズを2倍ずつ拡張していく。
【内部処理】
①現在のサイズより大きなサイズの新しい配列を生成
②現在の配列から新しい配列に値をコピー
③古い配列がGCによって回収・破棄される
Vector・ArrayListクラスはデフォルトのコンストラクタを
使用して初期化するとサイズは10となる。
オブジェクトの追加によって生成時に指定したサイズを超えて
しまった場合は、自動的に生成したコレクションクラスオブジェクト
のサイズを2倍ずつ拡張していく。
【内部処理】
①現在のサイズより大きなサイズの新しい配列を生成
②現在の配列から新しい配列に値をコピー
③古い配列がGCによって回収・破棄される
初期容量を適切にしてすることによって、この内部処理を
回避することができる。
回避することができる。
- 配列を使用してパフォーマンスを向上させる。
オブジェクトの配列は、コレクションクラスのようにサイズを
変更することはできない。初期化の際にあらかじめ配列のサイズは
指定しておく必要がある。しかし配列がもつメモリ量は
コレクションクラスと比較すると小さな量で、メソッドを呼び出す際の
コストも掛からない。したがって、サイズがあまり変更にならない
複数オブジェクトの操作を行うような場合には、
コレクションクラスより配列を使用したほうが
パフォーマンスは向上する。
変更することはできない。初期化の際にあらかじめ配列のサイズは
指定しておく必要がある。しかし配列がもつメモリ量は
コレクションクラスと比較すると小さな量で、メソッドを呼び出す際の
コストも掛からない。したがって、サイズがあまり変更にならない
複数オブジェクトの操作を行うような場合には、
コレクションクラスより配列を使用したほうが
パフォーマンスは向上する。
5.ループの終了条件はローカル変数にコピーする
【詳細】
ループが1回発生するたびに、終了条件を参照するので
10000回のループであれば、終了条件を10000回実行することになり、
終了条件によってはかなりのオーバーヘッドが発生する。
これを回避するために、終了条件をローカル変数にコピーする。
【詳細】
ループが1回発生するたびに、終了条件を参照するので
10000回のループであれば、終了条件を10000回実行することになり、
終了条件によってはかなりのオーバーヘッドが発生する。
これを回避するために、終了条件をローカル変数にコピーする。