- PR -

static修飾子は多用するべきか

投稿者投稿内容
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2005-12-17 07:37
引用:

そういえば、このまえ StringBuffer よりも String を使用したほうが速いという話をどこかで聞きました。従来、String よりも StringBuffer のほうが高速である、というのが定説でした。ところが、J2SE 5.0 の最適化では String は StringBuilder と同等のコードに置き換えられるため、同期不要な分だけ StringBuffer よりも速くなる可能性があるということでした。StringBuilder のインスタンス生成コストがあるので常に StringBuffer より速くなるわけではありませんが、速くなることもあると。


多分、コンパイラレベルでの最適化ですね。
JDK5.0以前からもJava言語仕様で規定されていますが、
JDK5.0からはStringBufferではなくStringBuilderに置き換えられるみたいですね。

これも聞いた話ですが、最近のSunやIBMのJVMは実行時の最適化に力を入れているらしく、
例えばバイトコード操作ライブラリで、有名なものではJavassistとASMがありますが、

・ASMは下手な最適化が行われており、実行時の最適化が行われにくい
・JavassistはJava言語仕様どおりにしかコンパイルしない。
 そのため、実行時の最適化の恩恵が受けられる

との事で、実行速度はJavassistの方が速いらしいです。
Seasar2のAOPも、上記理由からASMをやめてJavassistに変更したと、
作者のブログで読んだ覚えがあります。
yamasa
ベテラン
会議室デビュー日: 2003/02/15
投稿数: 80
投稿日時: 2005-12-17 16:53
引用:

Junさんの書き込み (2005-12-16 17:40) より:

ローカルなスタティックを使うことで通常再入可能では無いが(javaにはfinalは
あっても定数は無いのでおそらく)高速なメソッドを作れますよね
必ずしもメソッドがスレッドセーフであることが要求されないことを考えると
ローカルなスタティック変数ってあってもよさそうだけど,実際無いのは
何故かなって思うんですが(もしかしてあるのかも知れないが確かエラーになったような
気がします)


メソッド内でローカルに使うオブジェクトは、
生成・破棄のコストを減らすため、
static変数に置いたインスタンスを使い回すようにできないか
…ということを言っていますか?

だとしたら、JVMの進化はそういう小手先の技を
必要としないところまで来ています。
http://www-06.ibm.com/jp/developerworks/java/051104/j_j-jtp09275.shtml

エスケープ分析といえば、こういう話もありますね。
http://pcweb.mycom.co.jp/news/2005/12/13/020.html
この結果、StringBufferの余計な同期化が排除されるようになれば、
StringBuilderとの性能差は無くなってくるのかもしれません。
MUGEN
会議室デビュー日: 2005/04/05
投稿数: 1
投稿日時: 2008-05-28 00:41
[quote]
かつのりさんの書き込み (2005-12-16 18:53) より:
[quote]
staticフィールドは速いよ。
[/quote]
JDK1.1の頃の話でしょうか。
テストしてみましたが、インスタンスのフィールドアクセスと
クラスのフィールドアクセスの速度に殆ど差がありません。(JDK5.0)

現在のJVMでは最適化が行われていますし、
小手先の技ではむしろ最適化の邪魔になるケースもあるそうです。

検証コード(汚いですが・・・)
[code]
public class Test {

public static String classField = "classField";

public String instanceField = "instanceField";

public static int cCount = 0;

public static int iCount = 0;

public static void test(int n) {
String variable;
Test test = new Test();
variable = Test.classField;
long l1,l2,l3;

l1 = System.currentTimeMillis();
for(int i = 0; i < 50000000; i++){
variable = Test.classField;
}
l2 = System.currentTimeMillis();
for(int i = 0; i < 50000000; i++){
variable = test.instanceField;
}
l3 = System.currentTimeMillis();

System.out.println(n + ":l2 - l1 = " + (l2 - l1));
System.out.println(n + ":l3 - l2 = " + (l3 - l2));
if((l2 - l1) > (l3 - l2)){
cCount++;
}else if((l2 - l1) < (l3 - l2)){
iCount++;
}
}

public static void main(String[] args) {
for(int i = 0; i < 100; i++){
test(i);
}
System.out.println("cCount=" + cCount + ":iCount=" + iCount);
}
}
[/code]
[/quote]

かつのりさんのをall-in-oneで動かしたら、インスタンスの方が断然速かったんですが、以下のように書き換えたら、staticの方がはるかに速かったんですが???

public class Test {

public static String classField = "classField";

public String instanceField = "instanceField";

public static int cCount = 0;

public static int iCount = 0;

public static void stM() {

}

public void insM() {

}

public void test(int n) {
String variable;
// Test test = new Test();
variable = Test.classField;
long l1,l2,l3;

l1 = System.currentTimeMillis();
for(int i = 0; i < 50000000; i++){
// variable = Test.classField;
stM();
}
l2 = System.currentTimeMillis();
for(int i = 0; i < 50000000; i++){
// variable = test.instanceField;
insM();
}
l3 = System.currentTimeMillis();

// System.out.println(n + ":l2 - l1 = " + (l2 - l1));
// System.out.println(n + ":l3 - l2 = " + (l3 - l2));
System.out.println(n + ":sta = " + (l2 - l1));
System.out.println(n + ":ins = " + (l3 - l2));
if((l2 - l1) > (l3 - l2)){
cCount++;
}else if((l2 - l1) < (l3 - l2)){
iCount++;
}
}

public static void main(String[] args) {
Test test = new Test();
for(int i = 0; i < 100; i++){
test.test(i);
}
System.out.println("cCount=" + cCount + ":iCount=" + iCount);
}
}

_________________
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2008-05-28 10:33
かなり古い書き込みに・・・

手元のSunのJRE1.6(32bit)ではあんまり差がないというか、
実行毎によって変わりますね。

どっちにせよ、ランタイムのJITの最適化によってどうにでも変わりますので、
あまりstaticやインスタンスだのを気にする必要はないかと思います。
結局はVMの実装次第です。

全てのケースにおいて高速になるチューニングは難しいので、
より多数派のコードで早くなるようなチューニングを行うことが多いです。
ですので、現時点で速い遅いを気にせずに、
普通にコードを書いた方が得ですよということです。

スキルアップ/キャリアアップ(JOB@IT)