Portable Resource Control in Java The J-SEAL2 Approach 2018/12/29 Survey Portable Resource Control in Java The J-SEAL2 Approach hayami ※W. Binder, J. Hulaas, A. Villazón, and R. Vidal (OOPSLA-2001) 2018/12/29 全体ミーティング 全体ミーティング
J-SEAL2の概要 モバイルエージェント向けマイクロカーネル ドメイン単位で制御 さらに資源管理機能を付加 Pure Java 2018/12/29 J-SEAL2の概要 モバイルエージェント向けマイクロカーネル Pure Java 階層的なドメイン ドメイン単位で制御 ドメイン間の通信,安全な終了,… さらに資源管理機能を付加 CPU,ヒープメモリの使用量を制限 バイトコード変換で実現 2018/12/29 全体ミーティング 全体ミーティング
階層的なドメイン UntrustedなMO3は,serviceへのアクセスと使用する計算機資源が制限されるべき 2018/12/29 全体ミーティング
資源管理を行う背景 Javaには資源管理が不足 想定するアプリケーション 計算機資源(CPU,メモリ)独占の可能性 DoSアタックの危険性 拡張可能なデータベース Webブラウザ 2018/12/29 全体ミーティング
目的 複数のモバイルエージェントが安全に共存する基盤を提供 資源の独占を防止 あくまでPure Java 2018/12/29 全体ミーティング
アプローチ バイトコード変換 対象プログラム中に資源管理用コードを挿入 利点 欠点 ポータビリティを損なわない JITが利用できる 高オーバーヘッド 管理の精度 2018/12/29 全体ミーティング
目次 資源管理のためのAPI バイトコード変換による実装 実験 関連研究・まとめ 2018/12/29 全体ミーティング
資源管理のためのAPI 2018/12/29 全体ミーティング
管理対象とする計算機資源 CPU_RELATIVE:相対的なCPU時間(~%) MEM_ACITVE: heapメモリ(~MB) THREADS_ACTIVE THREADS_TOTAL DOMAINS_ACTIVE DOMAINS_TOTAL 2018/12/29 全体ミーティング
資源を操作するAPI~Res~ 資源のsplit public final class Res { public static final int CPU_RELATIVE = 0, MEM_ACTIVE = 1, THREADS_ACTIVE = 2, THREADS_TOTAL = 3, DOMAINS_ACTIVE = 4, DOMAINS_TOTAL = 5; public static Res getCurrentRes(int type); public int getType(); public long getLimit(); public long getUsage(); public Res split(long limit); public void setLimit(long limit); public void combine(); } 資源のsplit 2018/12/29 全体ミーティング
資源の分割(split) 親は自分に割り当てられた資源の中からいくらかを子に分け与える (split) 親,子,孫,…の資源割り当ての総和は一定 2018/12/29 全体ミーティング
Class ResSet 6種類のResを一括してドメインに関連付けるための補助クラス public final class ResSet { public static ResSet getCurrentResSet(); public ResSet copy(); public Res getRes(int type); public void setRes(Res r); public void combine(); } 2018/12/29 全体ミーティング
ドメイン操作のAPI~Seal~ public class Seal { // implements Serializable, Runnable public static void unwrap(WrappedSeal wrapped, String sealname, ResSet resources); ... } wrapされたドメイン (serializeされたモバイルエージェント) wrappedに,計算機資源resourcesを割り当て,名前sealnameで実行を開始する 2018/12/29 全体ミーティング
資源割り当ての例 childB childA 2018/12/29 全体ミーティング
APIを使った記述 親のCPU資源の75%をsplit 親のメモリ資源から10MBをsplit childAとchildBの実行開始 long MB = 1024*1024; ResSet rP = ResSet.getCurrentResSet(); Res cpu = rP.getRes(Res.CPU_RELATIVE); Res mem = rP.getRes(Res.MEM_ACTIVE); 親のCPU資源の75%をsplit ResSet rA = rP.copy(); long cpuA = (long)(cpu.getLimit()*0.75); rA.setRes(cpu.split(cpuA)); 親のメモリ資源から10MBをsplit ResSet rB = rP.copy(); rB.setRes(mem.split(10*MB)); childAとchildBの実行開始 Seal.unwrap(childA, nameOfChildA, rA); Seal.unwrap(childB, nameOfChildB, rB); 2018/12/29 全体ミーティング
バイトコード変換による実装 2018/12/29 全体ミーティング
バイトコード変換のタイミング classloaderを利用し、ロード時に変換 classfiles find “Foo.class” Transform “Foo.class” loadClass(“Foo”) JVM 2018/12/29 全体ミーティング
定義: ドメインのtype 各ドメインは管理する資源に応じて4つに分類される NO-ACC: 資源管理なし。バイトコード変換なし CPU-ACC: CPU資源のみ管理 MEM-ACC: メモリ資源のみ管理 CPU-MEM-ACC: CPU、メモリ両方管理 2018/12/29 全体ミーティング
定義: Accounting Objects 資源の現在の消費量と上限値を保持 usage: 現在の資源消費量 limit: usageの上限 e.g. public final class MemAccount { public long limit; public long usage=0; … } public final class CPUAccount { public int limit; public volatile int usage; … } 2018/12/29 全体ミーティング
ThreadLocalの利用 Accounting Objectへの参照はドメイン内のthread間で共有 各threadがThreadLocalとして保持 静的メソッド getCurrentAccount()で参照 e.g. ドメインA (CPU-MEM-ACC) MemAccounting thread1 instance thread2 … CPUAccounting … instance … 2018/12/29 全体ミーティング
変換アルゴリズム(メモリ) メモリ使用量をカウント Allocation直前にコード挿入 上限ckeck & object sizeだけカウンタを増加 Thread Localな変数memをget void foo() { Object a = new Object(); } MemAccount mem= MemAccount.getCurrentAccount(); mem.checkLimit(size_of_a); mem.usage += size_of_a; Limit check & increment 2018/12/29 全体ミーティング
ガベコレへの対応 配列以外のオブジェクト 配列オブジェクト finalizerにカウンタを減少するコードを挿入 弱参照(Weak Reference)を利用 c.f. java.lang.ref.WeakRefefence 解放されたオブジェクトへの弱参照はqueueへ queueは定期的に空にし、カウンタを減少 2018/12/29 全体ミーティング
変換アルゴリズム(CPU) CPU: 実行命令数をカウント 各基本ブロックの先頭にコード挿入 ブロック内の命令数分カウンタを増加 +3 +1 iconst_0 istore_0 goto 8 iinc 0 1 iload_0 ldc #1 <Integer 100> if_icmplt 5 return CPUAccounting cpu = CPUAccounting.getCurrentAccount(); cpu.usage += 3; 2018/12/29 全体ミーティング
高速化~引数を増やす~(1/2) 毎回“getCurrent~()”は遅い! 全メソッドの引数を1 or 2だけ増やす MemAccount / CPUAccount オブジェクトを引数で渡す 2018/12/29 全体ミーティング
高速化~引数を増やす~(2/2) Original: void a(int x) { b(null, x); } MEM-ACC void a(int x, MemAccount mem) { b(null, x, cpu); } void a(int x) { b(null, x); } CPU-ACC void a(int x, CPUAccount cpu) { b(null, x, cpu); } CPU-MEM-ACC void a(int x, MemAccount mem, CPUAccount cpu) { b(null, x, mem, cpu); } ※NO-ACCは変換の必要なし 2018/12/29 全体ミーティング
Shared classの扱い Shared Class (java.lang.*, java.io.*, …) ロード時の変換は不可能 ドメインのtypeを特定できない “off-line”で書き換え メソッドのオーバーロード コードサイズ4倍以上? 2018/12/29 全体ミーティング
Shared classの変換例 Original: void a(int x) { b(null, x); } オーバーロード MemAccount mem = MemAccount.getCurrentAccount(); CPUAccount cpu = CPUAccount.getCurrentAccount(); if (cpu == null) if (mem == null) a(x, (NoAccount)null); else a(x, mem); else if (mem == null) a(x, cpu); else a(x, mem, cpu); } void a(int x, NoAccount _no) { b(null, x, _no); } void a(int x, CPUAccount cpu) { b(null, x, cpu); } void a(int x, MemAccount mem) { b(null, x, mem); } void a(int x, MemAccount mem, CPUAccount cpu) { b(null, x, mem, cpu); オーバーロード Original: void a(int x) { b(null, x); } 2018/12/29 全体ミーティング
Limitations リフレクション ネイティブコード java.lang.Threadが貧弱 ネイティブコード中で使用される資源は管理できない java.lang.Threadが貧弱 2018/12/29 全体ミーティング
実験 ~CPU資源管理のオーバーヘッド~ 2018/12/29 全体ミーティング
実験 CPU資源管理によるオーバーヘッドを計測 SpecJVM98ベンチマークを実行 実験環境 Athlon1.2GHz, 256MB RAM, Linux kernel2.4.2 IBM JDK1.3, JIT 2018/12/29 全体ミーティング
設定の説明 Ubench-Ujdk Rbench-Ujdk Rbench-Rjdk ベンチマーク,shared classの両者とも無変更 ベンチマークだけ書き換え Rbench-Rjdk ベンチマーク,shared classの両者とも書き換え 2018/12/29 全体ミーティング
実験結果 (秒,時間比) 約25%のオーバーヘッド 2018/12/29 全体ミーティング
実験結果 2018/12/29 全体ミーティング
関連研究・まとめ 2018/12/29 全体ミーティング
関連研究 JRes KaffeOS Alta CPU, メモリ, ネットワーク資源管理 バイトコード変換+native コード 独自のJVM (Kaffe) Alta Based on Kaffe, nested processes 2018/12/29 全体ミーティング
結論 モバイルエージェントに適した資源管理 Pure Java,高いポータビリティー 階層的なドメイン 2018/12/29 全体ミーティング
参考文献 “Portable Resource Control in Java The J-SEAL2 Approach”, Walter Binder, Jarle G. Hulaas, Alex Villazón, OOPSLA-2001 “Resource Control in J-SEAL2”, Walter Binder, Jarle G.Hulaas, Alex Villaón, Technical Report, 2001 2018/12/29 全体ミーティング
付録 2018/12/29 全体ミーティング
付録: Static Initializer Static Initializer等,nativeコードから呼び出されるメソッドはシグニチャを変更不可 cinit() { … } cinit() { MemAccount mem = MemAccount.getCurrentAccount(); CPUAccount cpu = CPUAccount.getCurrentAccount(); cinit(mem, cpu); } cinit(MemAccount mem, CPUAccount cpu) { … 素直にThreadLocalからmem, cpuの値をget 2018/12/29 全体ミーティング