More Related Content Similar to 20130819 jjugnslt
Similar to 20130819 jjugnslt (20) 20130819 jjugnslt2. 自己紹介
v 名前: 竹林 信哉(たけばやし しんや)
v 職業: 某 SIer 社員 ・・・
少し前まで CGL 作っていました.今は Java サポート.
v 得意:
Ø OS 実装 / デバイスドライバ / UNIX / Windows
Ø C / C++ / asm(x86, SPARC) / Python / 並列(CUDA)
Ø コンパイラ,デバッガとお友達
v 私と Java
Ø プログラミング言語 Java は苦手です
Ø JavaVM の実装が大好き
@chi9rin
3. chi9 流 Hack の考え方
v 前提として
Ø アプリケーションは,そう簡単にソースコード通りに
動きません.
Ø 環境に依存して,書いたソースをまねて動きます.
Ø プログラマやアーキテクトの腕の見せ所は,いかに狙った環境
で狙ったとおりに動かすか,です.
4. chi9 流 Hack の考え方(Cont’d)
v だから
Ø ソースコードばかりを追っていても,答えが得られない可能性
があります.
Ø ソースコードと実際の動作を見て,初めて実装を理解できます.
ソースコードを読むのは予習
動いているものを trap して解析するのが Hack
6. -XX:+AggressiveHeap で
何が起きるか
計算
• メモリサイズ
• GC スレッド数
機能の有効化
• Parallel GC
• Large Pages
• JIT コンパイルポリシ
はシンプルモード
機能の無効化
• Scavenge GC
• TLAB の動的リサイズ
julong initHeapSize;
julong total_memory = os::physical_memory();
if (total_memory < (julong)256*M) {
jio_fprintf(defaultStream::error_stream(),
"You need at least 256mb of memory to use -XX:+AggressiveHeapn");
vm_exit(1);
}
initHeapSize = MIN2(total_memory / (julong)2, total_memory - (julong)160*M);
initHeapSize = os::allocatable_physical_memory(initHeapSize);
if (initHeapSize > MaxPermSize) {
initHeapSize = initHeapSize - MaxPermSize;
} else {
warning("AggressiveHeap and MaxPermSize values may conflict");
}
if (FLAG_IS_DEFAULT(MaxHeapSize)) {
FLAG_SET_CMDLINE(uintx, MaxHeapSize, initHeapSize);
FLAG_SET_CMDLINE(uintx, InitialHeapSize, initHeapSize);
set_min_heap_size(initHeapSize);
}
if (FLAG_IS_DEFAULT(NewSize)) {
FLAG_SET_CMDLINE(uintx, NewSize, ((julong)MaxHeapSize / (julong)8) * (julong)3);
FLAG_SET_CMDLINE(uintx, MaxNewSize, NewSize);
}
FLAG_SET_DEFAULT(UseLargePages, true);
FLAG_SET_CMDLINE(uintx, BaseFootPrintEstimate, MaxHeapSize);
FLAG_SET_CMDLINE(bool, ResizeTLAB, false);
FLAG_SET_CMDLINE(uintx, TLABSize, 256*K);
FLAG_SET_CMDLINE(uintx, YoungPLABSize, 256*K);
FLAG_SET_CMDLINE(uintx, OldPLABSize, 8*K);
FLAG_SET_CMDLINE(intx, CompilationPolicyChoice, 0);
FLAG_SET_CMDLINE(bool, UseParallelGC, true);
FLAG_SET_DEFAULT(ParallelGCThreads, Abstract_VM_Version::parallel_worker_threads());
FLAG_SET_CMDLINE(uintx, ThresholdTolerance, 100);
FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
FLAG_SET_CMDLINE(bool, BindGCTaskThreadsToCPUs, true);
7. 答え
パラメータ 最近のマシン環境で設定される値(青字は自動計算されるところ)
-Xmx(MaxHeapSize) 物理メモリ量の半分 – 約 85 MB(LP64 の場合)
-Xms(InitialHeapSize) MaxHeapSize と同じ
-XX:NewSize (MaxHeapSize ÷ 8) × 3
-XX:MaxNewSize NewSize と同値
-XX:+UseLargePages 有効化
-XX:BaseFootPrintEstimates MaxHeapSize と同値
-XX:-ResizeTLAB 無効化
-XX:TALBSize 256KB
-XX:YoungPLABSize 256KB
-XX:OldPLABSize 8KB
-XX:CompilationPolicyChoice 0(SimpleCompilePolicy)
-XX:+UseParallelGC 有効化
-XX:ParallelGCThreads CPU 数が 8 以下なら CPU 数と同値,9 以上なら後述の計算式
-XX:ThreasholdTolerance 100
-XX:-ScavengeBeforeFullGC 無効化
-XX:+BindGCTaskThreadsToCPUs 有効化
・ヒープ領域を多め(Aggressive!)に確保する.
・AP を全力(Aggressive!!)で走らせる.
・極力 GC しない.GC はまとめて全力(Aggressive!!!)で.
9. JavaVM の準備
% hg clone http://hg.openjdk.java.net/jdk7u/jdk7u2
% cd jdk7u2
% chmod +x ./get_source.sh; ./get_source.sh
% export ALT_BOOTDIR=/usr/lib/jvm/java-6-openjdk-amd64
% source jdk/make/jdk_generic_profile.sh
% make sanity && make ALLOW_DOWNLOAD=true debug_build
【注意】
・make -jn しないこと.
・gcc は 4.6 以前を使うこと.clang/clang++ は使わない.
・jdk7u25 以降は ZIP_DEBUGINFO_FILES=0 が必要
10. JavaVM 起動と進め方
v コマンドラインオプションを解析する箇所にブレイクポイントを
仕掛ける.
v signal 6(SIGABRT)を投げて core を分析しても good!
% ulimit –c unlimited
% gdb ./java
(gdb) b arguments.cpp:2458
No source file named arguments.cpp
Make breakpoint pending on future shared library load? (y or [N]) y
Breakpoint 1 (arguments.cpp:2458) pending.
(gdb) r -XX:+AggressiveHeap
...
Breakpoint 1, Arguments::parse_each_vm_init_arg ......
(gdb) signal 6
Continuing with signal SIGABRT.
[Thread 0x7ffff7fd0700 (LWP 21391) exited]
No unwaited-for children left.
11. 計算 その 1
そもそも AggressiveHeap が使えるかどうか
v 物理メモリの算出と閾値判定
Ø 物理メモリ量の算出
p = os::Linux::_physical_memory
= sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE)
= 物理ページ数 × ページサイズ = 513,535 × 4096 = 2,103,439,360
= /proc/meminfo の MemTotal 値 × 1,024(KB)
Ø 判定: 256 MB 未満なら AggressiveHeap は使えない
% gdb ./java
(gdb) b arguments.cpp:2446
(gdb) r -XX:+AggressiveHeap
Breakpoint 1, Arguments::parse_each_vm_init_arg (args=0x7ffff7fcfe20, scp_p=0x7ffff7fcea10, ...
(gdb) p total_memory
$1 = 2103439360
% grep MemTotal /proc/meminfo | awk '{print $2;}' | xargs -I n expr n * 1024
2103439360
julong total_memory = os::physical_memory();
if (total_memory < (julong)256*M) {
jio_fprintf(defaultStream::error_stream(),
"You need at least 256mb of memory to use -XX:+AggressiveHeapn");
vm_exit(1);
}
12. 計算 その 2
ヒープサイズの計算
v まず基準になるサイズを求め,次にヒープサイズを確定する.
p total_memory ÷ 2 または total_memory - 160 MB の小さい方
= 1,051,719,680 または 1,935,503,360 の小さい方
= 1,051,719,680
p = 1,051,719,680 – 87,241,520 = 964,478,160 (← LP64)
1,051,719,680 – 67,108,864 = 984,610,816(← それ以外)
% gdb ./java
(gdb) b arguments.cpp:2469
(gdb) r -XX:+AggressiveHeap
Breakpoint 1, Arguments::parse_each_vm_init_arg (args=0x7ffff7fcfe20, scp_p=0x7ffff7fcea10, ...
(gdb) p MaxPermSize
$2 = 87241520
(gdb) p initHeapSize
$1 = 964478160
initHeapSize = MIN2(total_memory) / (julong) 2, total_memory – (julong)160 * M);
if (initHeapSize > MaxPermSize) {
initHeapSize = initHeapSize - MaxPermSize;
} else {
warning("AggressiveHeap and MaxPermSize values may conflict");
}
13. 計算 その 2(Cont’d)
ヒープサイズの計算
v 確定した initHeapSize を MaxHeapSize,InitialHeapSize とし
て設定.
if (FLAG_IS_DEFAULT(MaxHeapSize)) {
FLAG_SET_CMDLINE(uintx, MaxHeapSize, initHeapSize);
FLAG_SET_CMDLINE(uintx, InitialHeapSize, initHeapSize);
set_min_heap_size(initHeapSize);
}
14. 計算 その 3
New 領域サイズの計算
v 算出した MaxHeapSize をもとに計算される.
Ø NewSize
p (MaxHeapSize / 8) * 3) = (964,478,160 ÷ 8) × 3
= 361,679,310
Ø MaxNewSize
p 上記で算出した NewSize と同値
% gdb ./java
(gdb) b arguments.cpp:2482
(gdb) r -XX:+AggressiveHeap
Breakpoint 1, Arguments::parse_each_vm_init_arg (args=0x7ffff7fcfe20, scp_p=0x7ffff7fcea10, ...
(gdb) p MaxHeapSize
$1 = 964478160
(gdb) p NewSize
$2 = 361679310
(gdb) p MaxNewSize
$3 = 361679310
FLAG_SET_CMDLINE(uintx, NewSize, ((julong)MaxHeapSize / (julong)8) * (julong)3);
FLAG_SET_CMDLINE(uintx, MaxNewSize, NewSize);
15. 計算 その 4
GC スレッド数の算出
v アクティブな CPU (/proc/cpuinfo の数)をもとに確定する.
Ø Abstract_VM_Version::nof_parallel_worker_threads()
p nof_parallel_worker_threads(num = 5, den = 8, switch_pt = 8)
アクティブな CPU 数に応じて適切な値が計算される.
p アクティブ CPU 数が 8 以下なら,アクティブな CPU 数と同値.
p 9 CPU 以上なら,8 + ((アクティブ CPU 数 – 8) × 5) ÷ 8)
例)アクティブ CPU 数が 72 なら 8 + ((72 – 8) × 5) ÷ 8) = 48 ス
レッド.
(gdb) b vm_version.cpp:307
(gdb) r -XX:+AggressiveHeap
...
Breakpoint 1, Abstract_VM_Version::parallel_worker_threads () at ...
(gdb) p _parallel_worker_threads
$1 = 4
unsigned int ncpus = (unsigned int) os::active_processor_count();
return (ncpus <= switch_pt) ? ncpus : (switch_pt + ((ncpus - switch_pt) * num) / den);
16. おさらい
パラメータ 最近のマシン環境で設定される値 GDB での出力 jinfo 出力
-Xmx(MaxHeapSize) 物理メモリ量の半分 – 約 85 MB -XX:MaxHeapSize=964478160
-Xms(InitialHeapSize) MaxHeapSize と同じ -XX:InitialHeapSize=964478160
-XX:NewSize (MaxHeapSize ÷ 8) × 3 -XX:NewSize=361679310
-XX:MaxNewSize NewSize と同値 -XX:MaxNewSize=361679310
-XX:+UseLargePages 有効化 -XX:+UseLargePages
-XX:BaseFootPrintEstimates MaxHeapSize と同値 -XX:BaseFootPrintEstimates=964478160
-XX:-ResizeTLAB 無効化 -XX:-ResizeTLAB
-XX:TLABSize 256KB -XX:TLABSize=262144
-XX:YoungPLABSize 256KB -XX:YoungPLABSize=262144
-XX:OldPLABSize 8KB -XX:OldPLABSize=8192
-XX:CompilationPolicyChoice 0(SimpleCompilePolicy) -XX:CompilationPolicyChoice=0
-XX:+UseParallelGC 有効化 -XX:+UseParallelGC
-XX:ParallelGCThreads CPU 数が 8 以下なら CPU 数と同値 -XX:ParallelGCThreads=4
-XX:ThresholdTolerance 100 -XX:ThresholdTolerance=100
-XX:-ScavengeBeforeFullGC 無効化 -XX:-ScavengeBeforeFullGC
-XX:+BindGCTaskThreadsToCPUs 有効化 -XX:+BindGCTaskThreadsToCPUs
(gdb) p MaxHeapSize
$1 = 964478160
(gdb) p InitialHeapSize
$2 = 964478160
(gdb) p NewSize
$3 = 361679310
(gdb) p MaxNewSize
$4 = 361679310
(gdb) p UseLargePages
$5 = true
(gdb) p BaseFootPrintEstimate
$6 = 964478160
(gdb) p ResizeTLAB
$7 = false
(gdb) p TLABSize
$8 = 262144
(gdb) p YoungPLABSize
$9 = 262144
(gdb) p OldPLABSize
$10 = 8192
(gdb) p CompilationPolicyChoice
$11 = 0
(gdb) p UseParallelGC
$12 = true
(gdb) p ParallelGCThreads
$13 = 4
(gdb) p ThresholdTolerance
$14 = 100
(gdb) p ScavengeBeforeFullGC
$15 = false
(gdb) p BindGCTaskThreadsToCPUs
$16 = true