Survey Portable Resource Control in Java The J-SEAL2 Approach hayami ※W. Binder, J. Hulaas, A. Villazón, and R. Vidal (OOPSLA-2001) 2015/10/1 全体ミーティング 1 J-SEAL2の概要 モバイルエージェント向けマイクロカーネル Pure Java 階層的なドメイン ドメイン単位で制御 ドメイン間の通信,安全な終了,… さらに資源管理機能を付加 CPU,ヒープメモリの使用量を制限 バイトコード変換で実現 2015/10/1 全体ミーティング 2 階層的なドメイン Untrustedな MO3は,service へのアクセスと 使用する計算機 資源が制限され るべき 2015/10/1 全体ミーティング 3 資源管理を行う背景 Javaには資源管理が不足 計算機資源(CPU,メモリ)独占の可能性 DoSアタックの危険性 想定するアプリケーション 拡張可能なデータベース Webブラウザ 2015/10/1 全体ミーティング 4 目的 複数のモバイルエージェントが安全に共存 する基盤を提供 資源の独占を防止 あくまでPure Java 2015/10/1 全体ミーティング 5 アプローチ バイトコード変換 対象プログラム中に資源管理用コードを挿入 利点 ポータビリティを損なわない JITが利用できる 欠点 高オーバーヘッド 管理の精度 2015/10/1 全体ミーティング 6 目次 資源管理のためのAPI バイトコード変換による実装 実験 関連研究・まとめ 2015/10/1 全体ミーティング 7 資源管理のためのAPI 2015/10/1 全体ミーティング 8 管理対象とする計算機資源 CPU_RELATIVE:相対的なCPU時間(~%) MEM_ACITVE: heapメモリ(~MB) THREADS_ACTIVE THREADS_TOTAL DOMAINS_ACTIVE DOMAINS_TOTAL 2015/10/1 全体ミーティング 9 資源を操作するAPI~Res~ 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); 資源のsplit public void setLimit(long limit); public void combine(); } 2015/10/1 全体ミーティング 10 資源の分割(split) 親は自分に割り当てられた資源の中から いくらかを子に分け与える (split) 親,子,孫,…の資源割り当ての総和は一定 2015/10/1 全体ミーティング 11 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(); } 2015/10/1 全体ミーティング 12 ドメイン操作のAPI~Seal~ public class Seal { // implements Serializable, Runnable } public static void unwrap(WrappedSeal wrapped, String sealname, ResSet resources); ... • wrapされたドメイン (serializeされたモバイルエージェント) wrappedに,計算機資源resourcesを割り当て,名前 sealnameで実行を開始する 2015/10/1 全体ミーティング 13 資源割り当ての例 childB childA 2015/10/1 全体ミーティング 14 APIを使った記述 long MB = 1024*1024; ResSet rP = ResSet.getCurrentResSet(); Res cpu = rP.getRes(Res.CPU_RELATIVE); Res mem = rP.getRes(Res.MEM_ACTIVE); ResSet rA = rP.copy(); long cpuA = (long)(cpu.getLimit()*0.75); rA.setRes(cpu.split(cpuA)); ResSet rB = rP.copy(); rB.setRes(mem.split(10*MB)); 親のCPU資源 の75%をsplit 親のメモリ資源 から10MBをsplit Seal.unwrap(childA, nameOfChildA, rA); Seal.unwrap(childB, nameOfChildB, rB); 2015/10/1 全体ミーティング childAとchildB の実行開始 15 バイトコード変換による実装 2015/10/1 全体ミーティング 16 バイトコード変換のタイミング classloaderを利用し、ロード時に変換 classfiles find “Foo.class” classloader loadClass(“Foo”) Transform “Foo.class” JVM 2015/10/1 全体ミーティング 17 定義: ドメインのtype 各ドメインは管理する資源に応じて4つに分 類される NO-ACC: 資源管理なし。バイトコード変換なし CPU-ACC: CPU資源のみ管理 MEM-ACC: メモリ資源のみ管理 CPU-MEM-ACC: CPU、メモリ両方管理 2015/10/1 全体ミーティング 18 定義: Accounting Objects 資源の現在の消費量と上限値を保持 usage: 現在の資源消費量 limit: usageの上限 e.g. 2015/10/1 public final class MemAccount { public long limit; public long usage=0; public final class CPUAccount { … public int limit; } public volatile int usage; … } 全体ミーティング 19 ThreadLocalの利用 Accounting Objectへの参照はドメイン内の thread間で共有 各threadがThreadLocalとして保持 静的メソッド getCurrentAccount()で参照 e.g. ドメインA (CPU-MEM-ACC) MemAccounting instance thread1 thread2 CPUAccounting instance 2015/10/1 全体ミーティング 20 変換アルゴリズム(メモリ) メモリ使用量をカウント Allocation直前にコード挿入 上限ckeck & object sizeだけカウンタを増加 Thread Local な変数memを get Limit check & increment 2015/10/1 void foo() { MemAccount mem= MemAccount.getCurrentAccount(); mem.checkLimit(size_of_a); mem.usage += size_of_a; Object a = new Object(); } 全体ミーティング 21 ガベコレへの対応 配列以外のオブジェクト finalizerにカウンタを減少するコードを挿入 配列オブジェクト 弱参照(Weak Reference)を利用 c.f. java.lang.ref.WeakRefefence 解放されたオブジェクトへの弱参照はqueueへ queueは定期的に空にし、カウンタを減少 2015/10/1 全体ミーティング 22 変換アルゴリズム(CPU) CPU: 実行命令数をカウント 各基本ブロックの先頭にコード挿入 ブロック内の命令数分カウンタを増加 iconst_0 istore_0 goto 8 +3 iload_0 ldc #1 <Integer 100> if_icmplt 5 +1 2015/10/1 return iinc 0 1 +1 +3 CPUAccounting cpu = CPUAccounting.getCurrentAccount(); cpu.usage += 3; 全体ミーティング 23 高速化~引数を増やす~(1/2) 毎回“getCurrent~()”は遅い! 全メソッドの引数を1 or 2だけ増やす MemAccount / CPUAccount オブジェクトを引 数で渡す 2015/10/1 全体ミーティング 24 高速化~引数を増やす~(2/2) Original: 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は変換の必要なし 2015/10/1 } 全体ミーティング 25 Shared classの扱い Shared Class (java.lang.*, java.io.*, …) ロード時の変換は不可能 ドメインのtypeを特定できない “off-line”で書き換え メソッドのオーバーロード コードサイズ4倍以上? 2015/10/1 全体ミーティング 26 Shared classの変換例 Original: void a(int x) { b(null, x); } 2015/10/1 void a(int 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); ド } 全体ミーティング 27 Limitations リフレクション ネイティブコード ネイティブコード中で使用される資源は管理で きない java.lang.Threadが貧弱 2015/10/1 全体ミーティング 28 実験 ~CPU資源管理のオーバーヘッド~ 2015/10/1 全体ミーティング 29 実験 CPU資源管理によるオーバーヘッドを計測 SpecJVM98ベンチマークを実行 実験環境 Athlon1.2GHz, 256MB RAM, Linux kernel2.4.2 IBM JDK1.3, JIT 2015/10/1 全体ミーティング 30 設定の説明 Ubench-Ujdk ベンチマーク,shared classの両者とも無変更 Rbench-Ujdk ベンチマークだけ書き換え Rbench-Rjdk ベンチマーク,shared classの両者とも書き換え 2015/10/1 全体ミーティング 31 実験結果 (秒,時間比) Benchmark mtrt jess compress db mpegaudio jack javac GeometricMean U bench -U jdk 3.783 (1.00) 5.299 (1.00) 11.605 (1.00) 19.775 (1.00) 4.484 (1.00) 4.120 (1.00) 9.400 (1.00) 6.970 (1.00) R bench -U jdk 4.517 (1.19) 5.842 (1.10) 13.344 (1.15) 20.443 (1.03) 6.316 (1.41) 4.294 (1.04) 10.643 (1.13) 7.989 (1.15) R bench -R jdk 4.788 (1.27) 6.415 (1.21) 13.449 (1.16) 23.381 (1.18) 6.345 (1.42) 5.033 (1.22) 12.401 (1.32) 8.717 (1.25) 約25%のオーバーヘッド 2015/10/1 全体ミーティング 32 実験結果 25 実行時間(秒) 20 15 Ubench-Ujdk Rbench-Ujdk Rbench-Rjdk 10 5 n et ric M ea jav ac k jac au dio pe g Ge om m co m pr db es s ss je m trt 0 2015/10/1 全体ミーティング 33 関連研究・まとめ 2015/10/1 全体ミーティング 34 関連研究 JRes CPU, メモリ, ネットワーク資源管理 バイトコード変換+native コード KaffeOS 独自のJVM (Kaffe) Alta Based on Kaffe, nested processes 2015/10/1 全体ミーティング 35 結論 モバイルエージェントに適した資源管理 Pure Java,高いポータビリティー 階層的なドメイン 2015/10/1 全体ミーティング 36 参考文献 “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 2015/10/1 全体ミーティング 37 付録 2015/10/1 全体ミーティング 38 付録: Static Initializer Static Initializer等,nativeコードから呼び出 されるメソッドはシグニチャを変更不可 cinit() { … } 2015/10/1 cinit() { MemAccount mem = MemAccount.getCurrentAccount(); CPUAccount cpu = CPUAccount.getCurrentAccount(); cinit(mem, cpu); 素直にThreadLocal } からmem, cpuの値 をget cinit(MemAccount mem, CPUAccount cpu) { … } 全体ミーティング 39
© Copyright 2024 ExpyDoc