top / index / prev / next / target / source
日記形式でつづる いがぴょんコラム ウェブページです。
最近SWTにハマっていました。とりあえず一通りSWTを理解できました。SWTのソースコードが これまた味わい深いんです。
ここんところ SWTにハマっていて 一通り堪能しました。(もちろんソースコードも堪能してます。そしてそのソースコードが大変味わい深いのです)いがぴょんの日記MLで盛り上がったSWTネタは またいつかホームページに転載します。とにかく SWTのおかげで デスクトップアプリケーションとしてのJava言語の可能性が大いに広がると私は確信しました。
ガベのこととか実行速度のこととかを考える必要があったので J2SE 1.4で導入されたNIOのCharBufferを試用してみました。 java.lang.StringBufferとjava.lang.Stringと そしてjava.nio.CharBufferとを比べてみよう、という企画です。乱暴なベンチマークみたいなものですが、この実験はとっても乱暴なものであるということを予め認識してから 後続の記載をお読み下さい。
Windows XP Pro SP1
Sun J2SE SDK 1.4.1_01 (Windows版)
調べてみてわかったのですが CharBufferは StringBufferを使うより高速でした。ざっくり2倍でしょうか。一方 Stringは 結果が戻ってきませんでした (苦笑)。ハナっからダメだったです。 Test.java
import java.nio.*;
public class Test {
private static final int LOOP = 5000000;
//private static final int LOOP = 10;
private static final boolean SHOW_RESULT_STRING = false;
public static final void main(String[] args) {
System.out.println("☆☆☆CharBuffer速度調査 超簡単サンプル☆☆☆");
System.out.println("まず最初に、可能ならメモリをきれいに掃除します。");
myGC();
showMemoryStatus();
System.out.println();
long start = System.currentTimeMillis();
testCharBuffer();
long end = System.currentTimeMillis();
System.out.println("CharBufferテスト所用ミリ秒:" + (end - start));
showMemoryStatus();
myGC();
showMemoryStatus();
System.out.println();
start = System.currentTimeMillis();
testStringBuffer();
end = System.currentTimeMillis();
System.out.println("StringBufferテスト所用ミリ秒:" + (end - start));
showMemoryStatus();
myGC();
showMemoryStatus();
System.out.println();
start = System.currentTimeMillis();
testString();
end = System.currentTimeMillis();
System.out.println("Stringテスト所用ミリ秒:" + (end - start));
showMemoryStatus();
myGC();
showMemoryStatus();
System.out.println();
}
private static final void myGC() {
System.out.println("ガベー時コレクション起動依頼");
Runtime.getRuntime().runFinalization();
Runtime.getRuntime().gc();
}
private static final void showMemoryStatus() {
Runtime rt = Runtime.getRuntime();
long totalMemory = rt.totalMemory();
long usingMemory = totalMemory - rt.freeMemory();
System.out.println("Memory: " + (usingMemory / 1024) + "/"
+ (totalMemory / 1024) + " KB (" + (usingMemory*100 / totalMemory) + "%)");
}
private static final void testString() {
String buf = new String();
for (int loop = 0;loop < LOOP;loop++) {
buf += "AB";
}
String result = buf;
if (SHOW_RESULT_STRING) {
System.out.println("結果:" + result);
}
}
private static final void testStringBuffer() {
StringBuffer buf = new StringBuffer();
for (int loop = 0;loop < LOOP;loop++) {
buf.append("AB");
}
String result = buf.toString();
if (SHOW_RESULT_STRING) {
System.out.println("結果:" + result);
}
}
private static final void testCharBuffer() {
CharBuffer buf = CharBuffer.allocate(LOOP * 2);
for (int loop = 0;loop < LOOP;loop++) {
buf = buf.put("AB");
}
String result = new String(buf.array());
if (SHOW_RESULT_STRING) {
System.out.println("結果:" + result);
}
}
}
実行結果、、、ここで判明したのですが、Stringの方が 数十分待っても処理が戻ってきません。 実行結果
D:\temp\test3>java Test☆☆☆CharBuffer速度調査 超簡単サンプル☆☆☆まず最初に、可能ならメモリをきれいに掃除します。ガベー時コレクション起動依頼
Memory: 153/1984 KB (7%)
CharBufferテスト所用ミリ秒:484
Memory: 39216/54840 KB (71%)ガベー時コレクション起動依頼
Memory: 153/56376 KB (0%)
StringBufferテスト所用ミリ秒:1219
Memory: 55450/64576 KB (85%)ガベー時コレクション起動依頼
Memory: 153/65088 KB (0%)…処理が戻ってこない
ということでループ回数を減らしてみて実行してみました。が、50000回にまで減らしても一向に戻ってきません。ということで java.lang.Stringクラスは論外ということに結論付きました (苦笑)
乱暴な結論
基本的に 速度やガベージコレクションが気になる場合には java.lang.Stringは極力利用しない
J2SE 1.4以上であれば CharBufferのような メモリ確保領域を意識しながら利用することが出来る高速なクラスが存在する