一個高性能並且功能比較全面的profiler庫,async-profiler 【Github地址】,可以作為 JProfiler 的開源替代。
async-profiler 提供了 CPU 熱點分析,內存分配采樣分析,鎖分析,時鍾分析,和Java函數(包括JVM native 函數)分析等功能,也提供了分析結果作為火焰圖輸出。
如何讀懂火焰圖參考阮一峰的博客 http://www.ruanyifeng.com/blog/2017/09/flame-graph.html
async-profiler 也提供了比較方便的啟動腳本,比如要采樣分析30s內的CPU熱點
./profiler.sh -e cpu -d 30 pid
使用 list 命令可以查看當前環境支持的分析事件,例如
./profiler.sh list pid
## output
Basic events:
cpu
alloc
lock
wall
itimer
Java method calls:
ClassName.methodName
Perf events:
page-faults
context-switches
cycles
instructions
cache-references
cache-misses
branch-instructions
branch-misses
bus-cycles
L1-dcache-load-misses
LLC-load-misses
dTLB-load-misses
rNNN
pmu/event-descriptor/
mem:breakpoint
trace:tracepoint
kprobe:func
uprobe:path
提供了一個oss的加速地址,
首先進入控制台,下載和解壓 async-profiler
curl -o async-profiler-2.5-linux-x64.tar.gz https://terminus-dice.oss-cn-hangzhou.aliyuncs.com/spot/java-agent/async-profiler/async-profiler-2.5-linux-x64.tar.gz
tar -zxvf async-profiler-2.5-linux-x64.tar.gz && cd async-profiler-2.5-linux-x64
然后 jps 查看 java 的進程 pid
jps
## output
1 app.jar
149 Jps
執行 cpu 熱點分析 ( 示例為進行 30秒的數據采樣,根據實際場景可以調整診斷周期
./profiler.sh -e cpu -d 30 1
## output
Profiling for 30 seconds
...
## ns 表示診斷周期內采樣到的函數執行時間
## percent 表示該函數的占比
## samples 表示函數被采樣到的次數
ns percent samples top
---------- ------- ------- ---
1170069916 3.55% 115 java_lang_Throwable::fill_in_stack_trace(Handle, methodHandle, Thread*)
1080180566 3.28% 106 CodeHeap::find_start(void*) const
979428580 2.97% 97 BacktraceBuilder::push(Method*, int, Thread*)
820367658 2.49% 70 IndexSetIterator::advance_and_next()
770204785 2.34% 74 OopMapSet::update_register_map(frame const*, RegisterMap*)
659625965 2.00% 63 _IO_vfprintf_internal
600066241 1.82% 59 frame::sender(RegisterMap*) const
559994122 1.70% 55 PhaseChaitin::Split(unsigned int, ResourceArea*)
500089045 1.52% 48 java.util.regex.Pattern$Slice.match
470039625 1.43% 45 vframeArray::allocate(JavaThread*, int, GrowableArray<compiledVFrame*>*, RegisterMap*, frame, frame, frame, bool)
430450575 1.31% 41 _int_malloc
409666771 1.24% 40 sun.net.www.ParseUtil.encodePath
400089494 1.21% 39 resource_allocate_bytes(unsigned long, AllocFailStrategy::AllocFailEnum)
380146025 1.15% 37 pthread_getspecific
371189901 1.13% 36 PhaseChaitin::interfere_with_live(unsigned int, IndexSet*)
360380475 1.09% 32 Deoptimization::fetch_unroll_info_helper(JavaThread*)
360090466 1.09% 35 jshort_disjoint_arraycopy
310034456 0.94% 31 RegisterMap::RegisterMap(RegisterMap const*)
280047136 0.85% 27 org.springframework.boot.loader.jar.JarFileEntries.getEntry
280007669 0.85% 28 CodeCache::find_blob(void*)
270352542 0.82% 27 _int_free
270065077 0.82% 26 nmethod::is_zombie() const
260038542 0.79% 25 __libc_malloc
執行內存分配分析 ( 示例為進行 30秒的數據采樣,根據實際場景可以調整診斷周期
./profiler.sh -e alloc -d 30 1
# output
Profiling for 30 seconds
...
## bytes 表示診斷周期內該類型觸發分配的總字節數
## percent 表示診斷周期內該類型觸發分配的總字節數占診斷周期內JVM分配總內存的比例
## samples 表示該類型被采樣到次數
bytes percent samples top
---------- ------- ------- ---
31107144 51.79% 171 char[]
5745504 9.57% 16 java.util.concurrent.locks.AbstractQueuedSynchronizer$Node
4189704 6.98% 9 int[]
3390448 5.65% 47 byte[]
3234784 5.39% 11 java.lang.String
1518048 2.53% 4 org.dozer.event.DozerEvent
1497888 2.49% 6 java.util.ArrayList$Itr
1319992 2.20% 6 java.util.HashMap$Node
922816 1.54% 1 java.util.regex.Pattern$Slice
890656 1.48% 3 java.lang.StringBuilder
759208 1.26% 2 java.lang.Object[]
618472 1.03% 1 org.springframework.boot.loader.jar.JarURLConnection
383064 0.64% 1 java.lang.String[]
379536 0.63% 1 org.springframework.asm.Label
379528 0.63% 1 org.springframework.asm.Item
379520 0.63% 1 java.nio.HeapCharBuffer
379520 0.63% 1 java.nio.HeapByteBuffer
379504 0.63% 1 java.util.LinkedList
379496 0.63% 1 java.util.LinkedList$Node
379496 0.63% 1 org.springframework.boot.loader.jar.JarURLConnection$JarEntryName
379496 0.63% 1 java.lang.Class[]
使用 -f profiler.html 參數輸出火焰圖,比如
./profiler.sh -e cpu -d 30 -f profiler.html 1
在容器內生成火焰圖文件
火焰圖打開效果