J 2 MEにおけるサイクルとStringの最適化


http://www.java3z.com/cwbwebhome/article/article7/766.html?id=1563
サイクルの最適化    サイクルを書くときは、カウント変数を0から始めて、それを積算する習慣があります。しかし、ちょっとした変更さえすれば、プログラムを速く走ることができます。サンプルプログラムは以下の通りです。
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class PerfTest extends MIDlet{
  public PerfTest(){}
  public void startApp(){
   long start,end ;
   start = System.currentTimeMillis() ;
   for(int i=0 ; i < 9000000 ; i++) ;
    end = System.currentTimeMillis() ;
   System.out.println("Normal loop : "+ (end-start) + " milliseconds") ;
 
   start = System.currentTimeMillis() ;
   for(int i=8999999 ; i >= 0 ; i--) ;
     end = System.currentTimeMillis() ;
   System.out.println("Optimized loop : "+ (end-start) + " milliseconds") ;
 }
 public void pauseApp(){}
 public void destroyApp(boolean unconditional){}
}
実行結果:Normal loop:2046 milisecondsOptimized loop:1563 milisecondsは上記の例から900万回走って、サイクルだけで約500ミリ秒違って、1/4の効率が上がることが分かります。この例は、比較演算子(>>>=、<、<=======>まで使用できるように拡張されます。有効なアップグレードができるのは、どの数値も0と比較すれば、下の階に簡単なコマンドが対応し、プログラムの実行が加速されるからです。サンプルの第一段プログラムコードは、0 invokestatic((zhi 2)3 lstre呷14 iconst_05 istore 57 goto 1310 iinc 5 113 iload 515 ldc嗳317 if_icmplt 1020 invokestatic啝223 lstre_324 get static攂427 new荖530 dup 31 invospecial 6>39 llad_340フォローアップ141 lsub 42 invokevirtual›945 ldc\38828;1047 invokevirtual鞬8二段目のプログラムコードは56 invokestatic((zhi 2)>59 lstre_にコンパイルされています。160 ldc菷1362 istore 664 goto 7067 iinc 6-170 iload 672 ifgt 6775 invokestatic咻278 lstor_379 get static擽482 new菗頸585 dup 86 invospecial堺694フォローアップ395フォローアップ196 lsb 97 invokevirtual›9<Method java.lang.StrigBuffer appnd(long)>100 ldc12080;10<String“miliseconds”102 invokevirtual鞬8<Methodjava.lang.StrigBuffer appnd(jantingggggggggggMaverappininininggggggggggggggMastststinininininininininininininininggggggggggggggstststststststinininininininininininininininininininingggg󑧙12import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class StringBufferTest extends MIDlet{ public StringBufferTest(){} public void startApp(){ Runtime rt = Runtime.getRuntime() ; long diffstart = rt.totalMemory()-rt.freeMemory(); System.out.println("Memory used Start:" + diffstart) ; // , , String String sum = "" ; for(int i=0 ; i< 5000 ; i++){ sum = sum + "+" + i ; } long diffend = rt.totalMemory()-rt.freeMemory(); System.out.println("Memory used End:" + diffend) ; System.out.println("Memory used after operation:" + (diffend-diffstart)) ; } public void pauseApp(){} public void destroyApp(boolean unconditional){} } 実行結果:Memory used Start:28564 Memory used End:2598646 Memory used after operation:231300このサンプルプログラムでは、Runtimeカテゴリのtotototal Memory()を使ってシステムのすべてのメモリサイズを取得し、free Memory()を使って利用可能なメモリのサイズを取得します。私たちは500回のループを実行して、約231300 byteのメモリを消費していることが分かります。もし私たちがStringをStringBufferで代用すれば:/StringBufferTest 1.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class StringBufferTest1 extends MIDlet{
  public StringBufferTest1(){}
  public void startApp(){
    Runtime rt = Runtime.getRuntime() ;
    long diffstart = rt.totalMemory()-rt.freeMemory();
    System.out.println("Memory used Start:" + diffstart) ;
 
   //  ,             ,     StringBuffer
    StringBuffer sum = new StringBuffer("");
    for(int i=0 ; i< 5000 ; i++){
      sum = sum.append("+").append(i) ;
    }
   long diffend = rt.totalMemory()-rt.freeMemory();
   System.out.println("Memory used End:" + diffend) ;
   System.out.println("Memory used after operation:" + (diffend-diffstart)) ;
  }
  public void pauseApp(){}
  public void destroyApp(boolean unconditional){}
}
実行結果:Memory used Start:28548 Memoryused End:160848 Memory used after operation:132300私達はString Bufferに変更した後に、循環は同様に500回実行して、同じ効果のプログラムコードですが、メモリは132300 byteのメモリだけを消費しました。ほぼ倍になりました。これはStringBufferが完全に取って代わることはできませんが、できればSteringBufferを使うようにしてください。メモリを節約する効果があるのは、Stringオブジェクトの設計にimmutableという設計パターンが採用されているからです。