程序在经过功能验证后,还需要经过性能测试,以便了解程序的性能情况以及是否在并发请求压力的情况下,还能够正常处理业务情况。特别是,长时间的压力测试情况下,观察程序是否存在内存泄漏等问题,性能是否大幅下降的问题等。
特别是经过压力测试并且性能出现大幅下降以后,或长时间(比如8小时或24小时)的压力测试以后的数据,更有代表性。
1. jmap查看堆内存
# jmap -heap 44603
Attaching to process ID 44603, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.152-b16
using thread-local object allocation.
Garbage-First (G1) GC with 10 thread(s)
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 2147483648 (2048.0MB)
NewSize = 1363144 (1.2999954223632812MB)
MaxNewSize = 1287651328 (1228.0MB)
OldSize = 5452592 (5.1999969482421875MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 536870912 (512.0MB)
G1HeapRegionSize = 4194304 (4.0MB)
Heap Usage:
G1 Heap:
regions = 512
capacity = 2147483648 (2048.0MB)
used = 960991440 (916.4728546142578MB)
free = 1186492208 (1131.5271453857422MB)
44.74965110421181% used
G1 Young Generation:
Eden Space:
regions = 164
capacity = 1333788672 (1272.0MB)
used = 687865856 (656.0MB)
free = 645922816 (616.0MB)
51.57232704402516% used
Survivor Space:
regions = 5
capacity = 20971520 (20.0MB)
used = 20971520 (20.0MB)
free = 0 (0.0MB)
100.0% used
G1 Old Generation:
regions = 61
capacity = 792723456 (756.0MB)
used = 252154064 (240.4728546142578MB)
free = 540569392 (515.5271453857422MB)
31.808578652679603% used
35786 interned Strings occupying 3746312 bytes.
主要是看内存的分配是否合理,是否存在某个分区被无限压缩到到极限(比如为0)的现象,另外的分区占用了整个堆空间,堆空间的可用内存为0的情况发生。
2. jmap查看内存对象直方图
# jmap -histo 44603 | head -30
num #instances #bytes class name
----------------------------------------------
1: 3164763 582161376 [C
2: 74586 128743408 [B
3: 176555 56414224 [I
4: 1942052 46609248 java.lang.String
5: 416990 26687360 java.net.URL
6: 570133 18244256 org.springframework.boot.loader.jar.StringSe
quence
7: 131593 10527440 org.springframework.boot.loader.jar.JarURLCo
nnection
8: 171114 8424984 [Ljava.lang.Object;
9: 285067 6841608 org.springframework.boot.loader.jar.JarURLCo
nnection$JarEntryName
10: 135618 6509664 java.util.HashMap
11: 75547 6150768 [Ljava.util.HashMap$Node;
12: 186801 5977632 java.util.HashMap$Node
13: 81649 5878728 oracle.jdbc.driver.T4CTTIoac
14: 6319 5712376 oracle.jdbc.driver.T4CPreparedStatement
15: 224854 5396496 java.util.LinkedList$Node
16: 50440 4704576 [S
17: 74759 4186504 java.util.stream.ReferencePipeline$Head
18: 36379 3201352 java.lang.reflect.Method
19: 121277 2910648 java.util.ArrayList
20: 26560 2790616 [J
21: 65641 2625640 java.util.LinkedHashMap$Entry
主要是看这里是否有对象的数量只增不减,占用的空间还很大的情况发生。
3. jstat查看内存及垃圾回收信息
# jstat -gcutil 44603 3000
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 100.00 16.51 27.65 91.66 87.40 42942 330.447 0 0.000 330.447
0.00 100.00 43.49 27.95 91.66 87.40 42946 330.481 0 0.000 330.481
0.00 100.00 61.90 28.46 91.66 87.40 42950 330.514 0 0.000 330.514
0.00 100.00 66.25 28.82 91.66 87.40 42954 330.549 0 0.000 330.549
0.00 100.00 78.10 29.31 91.66 87.40 42958 330.582 0 0.000 330.582
0.00 100.00 2.22 29.56 91.66 87.40 42963 330.629 0 0.000 330.629
0.00 100.00 27.76 30.02 91.66 87.40 42967 330.663 0 0.000 330.663
0.00 100.00 58.81 30.20 91.66 87.40 42971 330.694 0 0.000 330.69
主要是看垃圾回收的频次和效果,特别是FGC次数过于频繁,对性能的影响是很大的。老年代的占用比例如果持续在高位,则存在内存泄漏的风险。
4. 导出堆内存用于分析
jmap -dump:live,format=b,file=heap.hprof <pid>
执行此命令时,会进行垃圾回收,对于能够回收的对象,不会在导出的文件中提现。
用eclipse memory analysis 工具分析。
Window==>Perspective ==> Open Perspective ==> Others == > Memory Analysis
然后再从File ==> Open Heap Dump ...
打开对应的转储文件。
直方图:
依赖树:
从直方图和依赖树,可以看出内存中有大量的对象没有被释放,占到堆内存空间的91.73%,超过1GB的空间大小。