第4回:実機に載せよう(ダウンサイズ)
improve の ダウンサイズ
「ダウンサイズの実際」
その0 ダウンサイズ計画
ダウンサイズの順序
- アルゴリズム最適化
- 即値の利用
- メソッド削除
- メソッドのインライン化
- フィールド削除
- 定数展開
- 変数配列化
- クラス融合
- 名前の共有・短縮
1. アルゴリズム最適化
メソッド内の未使用変数削除とか、機能未実装で書きかけのコードなどを削除します。
例.
■ 変更前
FriendMenu クラスの commandAction メソッド if( c.equals(cancelCommand) ){ ImproveMIDlet.setCurrent(ImproveMIDlet.listCanvas); } else if( c.equals(okCommand) ){ switch(cursor){ case ITEM_INFO: break; default: break; } ImproveMIDlet.setCurrent(ImproveMIDlet.listCanvas); }
■ 変更後
if( c.equals(cancelCommand) || c.equals(okCommand) ){ ImproveMIDlet.setCurrent(ImproveMIDlet.listCanvas); }
2. 即値の利用
たとえば、ImproveMIDlet のコンストラクタで
Timer timer = new Timer(); timer.scheduleAtFixedRate(task,200,200);
という部分を
new Timer().scheduleAtFixedRate(task,200,200);
にするように、保持する必要の無いクラスを変数に割り当てないように変えていきました。
3. メソッド削除
Taskクラスの
/** 返り値の取得 */ public Object getReturnValue() { return returnValue; }
などのメソッドを削除しました。
その4 メソッドのインライン化
ゲッター、セッターを展開しました。これらはメソッドを削除して、そのフィールドを public に変えて、ゲッターセッターを使用しているコードを直接代入などに変えるだけです。
Message クラスの
public String getAccount(){ return account; }
の場合、このメソッドを削除して、フィールド account を private から public に変え、呼出部分の m.getAccount() を m.account に変えるだけです。m は Message のインスタンスです。
5. フィールド削除
Task クラスのメソッド
public int getProcessorStatus() { return status; }
を未使用で削除したので、それに伴って status の値を使う部分が無いため、status に代入するコードを消しました。
6. 定数展開
定数は static final な変数のことです。
public static final int ACCOUNT_MAX = 10;
定数フィールドを定数の値に置き換えます。
7. 変数配列化
同じ型のフィールドを配列にしていく作業です。
8. クラス融合
クラス融合とは 2 つ以上のクラスを一つにする作業です。
クラス融合できる条件として具体的には、”親クラスが同じ、もしくはどちらかの親クラスが無い(java.lang.Object である)”場合です。ただし、何度もインスタンスを作成するような小さなクラスを大きな(親クラスも含めて!)クラスに共有してしまうと、小さなクラスのインスタンス作成が非常に遅くなったり、メモリを無駄に消費してしまう、というデメリットがあります。
9. 名前の共有・短縮
クラス名、フィールド名、メソッド名をできるだけ共有し短縮します。
クラス内フィールドの型を表す文字列として"I"( int )や"Z"( boolean )があります。その型(int や boolean )を使用している場合は優先してその名前("I","Z")に変えます。そうすることで"I"や"Z"の名前が、かたやクラス名、かたやフィールドとなり、共有されます。
ダウンサイズ後ソース一覧
クラス | 元のクラス |
---|---|
A | Buddy |
B | BuddyListCanvas |
C | BuddyListMenu |
D | CreateTask, ChangeStatusMenu |
E | DeleteTask, TwoChoiceMenu |
F | FollowedByPollingTask |
G | FriendMenu |
H | ImproveAbstractCanvas |
I | ImproveMIDlet, Ticker, ResourceManager |
J | MainMenu |
K | Message |
L | MessageBox |
M | MessagingCanvas |
N | PollingTask |
Z | Task, Menu, (Constants) |
こちらのアーカイブもご利用ください。
SophiaCompress(Java) を使った場合
手作業とSophiaCompress(Java) でのダウンサイズを比較します。
作業項目 | 手作業 | SophiaCompress(Java) | ||
---|---|---|---|---|
時間 | 圧縮率 | 時間 | 圧縮率 ※ | |
合計 | 9.00 | 29.37% | 0.05 | 23.94% |
0.ダウンサイズ計画 | 0.50 | - | - | - |
1, 2.アルゴリズム最適化・即値の利用 | 1.25 | 0.28% | - | × |
3, 4.メソッド削除・インライン化 | 0.50 | 1.83% | - | × |
5, 6.フィールド削除・定数展開 | 1.50 | 8.95% | - | ○ |
7.フィールド配列化 | 0.75 | 1.41% | - | × |
8.クラス融合 | 1.50 | 5.54% | - | × |
9.名前・文字列の共有・短縮 | 3.00 | 14.92% | - | ○ |
※ この記事が書かれた 2003 年 4 月当時は SophiaCompress(Java) はクラス融合機能を搭載していませんでした。現在ではクラス融合機能も搭載していますので、圧縮率が大幅に向上しています。( 2006 年 4 月 )
まとめ
- Java のクラスファイルの構造を、コンスタントプールを中心に説明しました。
- Java VM の簡単な仕組みと、インストラクションの概要を説明しました。
- Class2HTML を用い、クラスファイルを覗いてみました。
- Class Construction Kit を用い、クラスファイルを変更しました。
- improve をダウンサイズしてみました。
- 手作業のダウンサイズと SophiaCompress(Java) によるダウンサイズを比較しました。
参考文献
- Java バーチャルマシン (オライリー・ジャパン ISBN 4-900900-63-X)
- Java 仮想マシン仕様 第2版 (ピアソン・エディケーション ISBN 4-89471-356-X)