Java速度较慢,堆较大,没有过多的gc调用 原始问题

Java速度较慢,堆较大,没有过多的gc调用 原始问题,java,performance,jvm,heap-memory,Java,Performance,Jvm,Heap Memory,我正在运行一个Java程序,比如program.jar,它有一个“小”初始堆(1gb)和一个“大”初始堆(16gb)。当我使用小的初始堆运行它时,即 java -jar -Xms1g -Xmx16g program.jar java -jar -Xms16g -Xmx16g program.jar 程序在12秒后终止(多次运行的平均值)。相反,当我使用较大的初始堆运行它时,即 java -jar -Xms1g -Xmx16g program.jar java -jar -Xms16g -X

我正在运行一个Java程序,比如program.jar,它有一个“小”初始堆(1gb)和一个“大”初始堆(16gb)。当我使用小的初始堆运行它时,即

java -jar -Xms1g -Xmx16g program.jar
java -jar -Xms16g -Xmx16g program.jar
程序在12秒后终止(多次运行的平均值)。相反,当我使用较大的初始堆运行它时,即

java -jar -Xms1g -Xmx16g program.jar
java -jar -Xms16g -Xmx16g program.jar
程序在30秒后终止(多次运行的平均值)

我从其他问题中了解到,通常情况下,大堆可能会导致过度垃圾收集,从而减慢程序:

> free
             total       used       free     shared    buffers     cached
Mem:      65588960   31751316   33837644         20     154616   23995164
-/+ buffers/cache:    7601536   57987424
Swap:      1023996      11484    1012512

但是,当我运行带有标志
-verbose:gc
的program.jar时,对于较大的初始堆,不会报告任何gc活动。对于较小的初始堆,在我开始测量时间之前,在程序的初始化阶段只有一些gc活动。因此,过度收集垃圾似乎并不能澄清我的观察结果

为了让它更混乱(至少对我来说),我有一个功能相当的程序,比如program2.jar,它具有与program.jar相同的输入输出行为。主要区别在于program2.jar使用的数据结构比program.jar效率低,至少在内存方面是如此(实际上,我正试图确定program2.jar是否在时间方面效率较低)。但是,无论我使用小的初始堆还是大的初始堆运行program2.jar,它总是在大约22秒后终止(包括大约2-3秒的gc调用)

所以,这是我的问题:(如何)大堆会降低程序的速度,而不考虑过多的垃圾收集?

(这个问题可能与Georg在“”中的问题相似,但他的问题与堆无关。在我的例子中,我觉得它一定与堆有关,因为这是两次运行program.jar的唯一区别。)

以下是一些可能相关的细节。我使用的是Java 7,OpenJDK:

> java -version
java version "1.7.0_75"
OpenJDK Runtime Environment (rhel-2.5.4.0.el6_6-x86_64 u75-b13)
OpenJDK 64-Bit Server VM (build 24.75-b04, mixed mode)
我的机器在两个插槽中有两个E5-2690V3处理器()(禁用了超线程和Turbo Boost),并且有足够的内存(64gb),其中大约一半在运行程序之前是空闲的:

> free
             total       used       free     shared    buffers     cached
Mem:      65588960   31751316   33837644         20     154616   23995164
-/+ buffers/cache:    7601536   57987424
Swap:      1023996      11484    1012512
最后,程序有多个线程(大约70个)

编辑1 回应和

我收集了一些额外的统计数据。这适用于具有小初始堆的program.jar:

Command being timed: "java -Xms1g -Xmx16g -verbose:gc -jar program.jar"
User time (seconds): 339.11
System time (seconds): 29.86
Percent of CPU this job got: 701%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:52.61
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 12192224
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 1
Minor (reclaiming a frame) page faults: 771372
Voluntary context switches: 7446
Involuntary context switches: 27788
Swaps: 0
File system inputs: 10216
File system outputs: 120
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
Command being timed: "java -Xms16g -Xmx16g -verbose:gc -jar program.jar"
User time (seconds): 769.13
System time (seconds): 28.04
Percent of CPU this job got: 1101%
Elapsed (wall clock) time (h:mm:ss or m:ss): 1:12.34
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 10974528
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 16
Minor (reclaiming a frame) page faults: 687727
Voluntary context switches: 6769
Involuntary context switches: 68465
Swaps: 0
File system inputs: 2032
File system outputs: 160
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
[GC [PSYoungGen: 239882K->33488K(306176K)] 764170K->983760K(1271808K), 0.0840630 secs] [Times: user=0.70 sys=0.66, real=0.09 secs]
[Full GC [PSYoungGen: 33488K->0K(306176K)] [ParOldGen: 950272K->753959K(1508352K)] 983760K->753959K(1814528K) [PSPermGen: 2994K->2993K(21504K)], 0.0560900 secs] [Times: user=0.20 sys=0.03, real=0.05 secs]
[GC [PSYoungGen: 234744K->33056K(306176K)] 988704K->983623K(1814528K), 0.0416120 secs] [Times: user=0.69 sys=0.03, real=0.04 secs]
[GC [PSYoungGen: 264198K->33056K(306176K)] 1214765K->1212999K(1814528K), 0.0489600 secs] [Times: user=0.61 sys=0.23, real=0.05 secs]
[Full GC [PSYoungGen: 33056K->0K(306176K)] [ParOldGen: 1179943K->1212700K(2118656K)] 1212999K->1212700K(2424832K) [PSPermGen: 2993K->2993K(21504K)], 0.1589640 secs] [Times: user=2.27 sys=0.10, real=0.16 secs]
[GC [PSYoungGen: 230538K->33056K(431616K)] 1443238K->1442364K(2550272K), 0.0523620 secs] [Times: user=0.69 sys=0.23, real=0.05 secs]
[GC [PSYoungGen: 427431K->33152K(557568K)] 1836740K->1835676K(2676224K), 0.0774750 secs] [Times: user=0.64 sys=0.72, real=0.08 secs]
[Full GC [PSYoungGen: 33152K->0K(557568K)] [ParOldGen: 1802524K->1835328K(2897920K)] 1835676K->1835328K(3455488K) [PSPermGen: 2993K->2993K(21504K)], 0.2019870 secs] [Times: user=2.74 sys=0.13, real=0.20 secs]
[GC [PSYoungGen: 492503K->33280K(647168K)] 2327831K->2327360K(3545088K), 0.0870810 secs] [Times: user=0.61 sys=0.92, real=0.09 secs]
[Full GC [PSYoungGen: 33280K->0K(647168K)] [ParOldGen: 2294080K->2326876K(3603968K)] 2327360K->2326876K(4251136K) [PSPermGen: 2993K->2993K(21504K)], 0.0512730 secs] [Times: user=0.09 sys=0.12, real=0.05 secs]

Heap
 PSYoungGen  total 647168K, used 340719K [0x00000006aaa80000, 0x00000006dd000000, 0x0000000800000000)
  eden space 613376K, 55% used [0x00000006aaa80000,0x00000006bf73bc10,0x00000006d0180000)
  from space 33792K, 0% used [0x00000006d2280000,0x00000006d2280000,0x00000006d4380000)
  to   space 33792K, 0% used [0x00000006d0180000,0x00000006d0180000,0x00000006d2280000)
 ParOldGen   total 3603968K, used 2326876K [0x0000000400000000, 0x00000004dbf80000, 0x00000006aaa80000)
  object space 3603968K, 64% used [0x0000000400000000,0x000000048e0572d8,0x00000004dbf80000)
 PSPermGen   total 21504K, used 3488K [0x00000003f5a00000, 0x00000003f6f00000, 0x0000000400000000)
  object space 21504K, 16% used [0x00000003f5a00000,0x00000003f5d68070,0x00000003f6f00000)
Heap
 PSYoungGen  total 4893696K, used 2840362K [0x00000006aaa80000, 0x0000000800000000, 0x0000000800000000)
  eden space 4194816K, 67% used [0x00000006aaa80000,0x000000075804a920,0x00000007aab00000)
  from space 698880K, 0% used [0x00000007d5580000,0x00000007d5580000,0x0000000800000000)
  to   space 698880K, 0% used [0x00000007aab00000,0x00000007aab00000,0x00000007d5580000)
 ParOldGen   total 11185152K, used 0K [0x00000003fff80000, 0x00000006aaa80000, 0x00000006aaa80000)
  object space 11185152K, 0% used [0x00000003fff80000,0x00000003fff80000,0x00000006aaa80000)
 PSPermGen   total 21504K, used 3489K [0x00000003f5980000, 0x00000003f6e80000, 0x00000003fff80000)
  object space 21504K, 16% used [0x00000003f5980000,0x00000003f5ce8400,0x00000003f6e80000)
这适用于初始堆较大的program.jar:

Command being timed: "java -Xms1g -Xmx16g -verbose:gc -jar program.jar"
User time (seconds): 339.11
System time (seconds): 29.86
Percent of CPU this job got: 701%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:52.61
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 12192224
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 1
Minor (reclaiming a frame) page faults: 771372
Voluntary context switches: 7446
Involuntary context switches: 27788
Swaps: 0
File system inputs: 10216
File system outputs: 120
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
Command being timed: "java -Xms16g -Xmx16g -verbose:gc -jar program.jar"
User time (seconds): 769.13
System time (seconds): 28.04
Percent of CPU this job got: 1101%
Elapsed (wall clock) time (h:mm:ss or m:ss): 1:12.34
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 10974528
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 16
Minor (reclaiming a frame) page faults: 687727
Voluntary context switches: 6769
Involuntary context switches: 68465
Swaps: 0
File system inputs: 2032
File system outputs: 160
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
[GC [PSYoungGen: 239882K->33488K(306176K)] 764170K->983760K(1271808K), 0.0840630 secs] [Times: user=0.70 sys=0.66, real=0.09 secs]
[Full GC [PSYoungGen: 33488K->0K(306176K)] [ParOldGen: 950272K->753959K(1508352K)] 983760K->753959K(1814528K) [PSPermGen: 2994K->2993K(21504K)], 0.0560900 secs] [Times: user=0.20 sys=0.03, real=0.05 secs]
[GC [PSYoungGen: 234744K->33056K(306176K)] 988704K->983623K(1814528K), 0.0416120 secs] [Times: user=0.69 sys=0.03, real=0.04 secs]
[GC [PSYoungGen: 264198K->33056K(306176K)] 1214765K->1212999K(1814528K), 0.0489600 secs] [Times: user=0.61 sys=0.23, real=0.05 secs]
[Full GC [PSYoungGen: 33056K->0K(306176K)] [ParOldGen: 1179943K->1212700K(2118656K)] 1212999K->1212700K(2424832K) [PSPermGen: 2993K->2993K(21504K)], 0.1589640 secs] [Times: user=2.27 sys=0.10, real=0.16 secs]
[GC [PSYoungGen: 230538K->33056K(431616K)] 1443238K->1442364K(2550272K), 0.0523620 secs] [Times: user=0.69 sys=0.23, real=0.05 secs]
[GC [PSYoungGen: 427431K->33152K(557568K)] 1836740K->1835676K(2676224K), 0.0774750 secs] [Times: user=0.64 sys=0.72, real=0.08 secs]
[Full GC [PSYoungGen: 33152K->0K(557568K)] [ParOldGen: 1802524K->1835328K(2897920K)] 1835676K->1835328K(3455488K) [PSPermGen: 2993K->2993K(21504K)], 0.2019870 secs] [Times: user=2.74 sys=0.13, real=0.20 secs]
[GC [PSYoungGen: 492503K->33280K(647168K)] 2327831K->2327360K(3545088K), 0.0870810 secs] [Times: user=0.61 sys=0.92, real=0.09 secs]
[Full GC [PSYoungGen: 33280K->0K(647168K)] [ParOldGen: 2294080K->2326876K(3603968K)] 2327360K->2326876K(4251136K) [PSPermGen: 2993K->2993K(21504K)], 0.0512730 secs] [Times: user=0.09 sys=0.12, real=0.05 secs]

Heap
 PSYoungGen  total 647168K, used 340719K [0x00000006aaa80000, 0x00000006dd000000, 0x0000000800000000)
  eden space 613376K, 55% used [0x00000006aaa80000,0x00000006bf73bc10,0x00000006d0180000)
  from space 33792K, 0% used [0x00000006d2280000,0x00000006d2280000,0x00000006d4380000)
  to   space 33792K, 0% used [0x00000006d0180000,0x00000006d0180000,0x00000006d2280000)
 ParOldGen   total 3603968K, used 2326876K [0x0000000400000000, 0x00000004dbf80000, 0x00000006aaa80000)
  object space 3603968K, 64% used [0x0000000400000000,0x000000048e0572d8,0x00000004dbf80000)
 PSPermGen   total 21504K, used 3488K [0x00000003f5a00000, 0x00000003f6f00000, 0x0000000400000000)
  object space 21504K, 16% used [0x00000003f5a00000,0x00000003f5d68070,0x00000003f6f00000)
Heap
 PSYoungGen  total 4893696K, used 2840362K [0x00000006aaa80000, 0x0000000800000000, 0x0000000800000000)
  eden space 4194816K, 67% used [0x00000006aaa80000,0x000000075804a920,0x00000007aab00000)
  from space 698880K, 0% used [0x00000007d5580000,0x00000007d5580000,0x0000000800000000)
  to   space 698880K, 0% used [0x00000007aab00000,0x00000007aab00000,0x00000007d5580000)
 ParOldGen   total 11185152K, used 0K [0x00000003fff80000, 0x00000006aaa80000, 0x00000006aaa80000)
  object space 11185152K, 0% used [0x00000003fff80000,0x00000003fff80000,0x00000006aaa80000)
 PSPermGen   total 21504K, used 3489K [0x00000003f5980000, 0x00000003f6e80000, 0x00000003fff80000)
  object space 21504K, 16% used [0x00000003f5980000,0x00000003f5ce8400,0x00000003f6e80000)
(此处报告的挂钟时间与我在原始帖子中报告的时间不同,因为之前有一个未计时的初始化阶段。)

编辑2 响应8472的首字母和后面的字母

我收集了一些关于缓存的统计数据。这适用于初始堆较小的program.jar(平均运行30次):

这适用于初始堆较大的program.jar(平均运行30次):

比较绝对数,较大的初始堆会导致L1 dcache负载未命中增加约50%,dTLB负载未命中增加70%。我对dTLB加载未命中进行了一次封套后计算,假设在我的2.6 ghz机器上有100个循环/未命中(源代码:),这使得大初始堆的延迟为484秒,而小初始堆的延迟为284秒。我不知道如何将这个数字转换回每个内核的延迟(可能不只是除以内核的数量?),但数量级似乎是合理的

在收集了这些统计数据之后,我还对大型和小型初始堆的
-XX:+PrintFlagsFinal
输出进行了区分(基于这两种情况中每一种的一次运行):

对于初始堆较大的program.jar:

Command being timed: "java -Xms1g -Xmx16g -verbose:gc -jar program.jar"
User time (seconds): 339.11
System time (seconds): 29.86
Percent of CPU this job got: 701%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:52.61
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 12192224
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 1
Minor (reclaiming a frame) page faults: 771372
Voluntary context switches: 7446
Involuntary context switches: 27788
Swaps: 0
File system inputs: 10216
File system outputs: 120
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
Command being timed: "java -Xms16g -Xmx16g -verbose:gc -jar program.jar"
User time (seconds): 769.13
System time (seconds): 28.04
Percent of CPU this job got: 1101%
Elapsed (wall clock) time (h:mm:ss or m:ss): 1:12.34
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 10974528
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 16
Minor (reclaiming a frame) page faults: 687727
Voluntary context switches: 6769
Involuntary context switches: 68465
Swaps: 0
File system inputs: 2032
File system outputs: 160
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
[GC [PSYoungGen: 239882K->33488K(306176K)] 764170K->983760K(1271808K), 0.0840630 secs] [Times: user=0.70 sys=0.66, real=0.09 secs]
[Full GC [PSYoungGen: 33488K->0K(306176K)] [ParOldGen: 950272K->753959K(1508352K)] 983760K->753959K(1814528K) [PSPermGen: 2994K->2993K(21504K)], 0.0560900 secs] [Times: user=0.20 sys=0.03, real=0.05 secs]
[GC [PSYoungGen: 234744K->33056K(306176K)] 988704K->983623K(1814528K), 0.0416120 secs] [Times: user=0.69 sys=0.03, real=0.04 secs]
[GC [PSYoungGen: 264198K->33056K(306176K)] 1214765K->1212999K(1814528K), 0.0489600 secs] [Times: user=0.61 sys=0.23, real=0.05 secs]
[Full GC [PSYoungGen: 33056K->0K(306176K)] [ParOldGen: 1179943K->1212700K(2118656K)] 1212999K->1212700K(2424832K) [PSPermGen: 2993K->2993K(21504K)], 0.1589640 secs] [Times: user=2.27 sys=0.10, real=0.16 secs]
[GC [PSYoungGen: 230538K->33056K(431616K)] 1443238K->1442364K(2550272K), 0.0523620 secs] [Times: user=0.69 sys=0.23, real=0.05 secs]
[GC [PSYoungGen: 427431K->33152K(557568K)] 1836740K->1835676K(2676224K), 0.0774750 secs] [Times: user=0.64 sys=0.72, real=0.08 secs]
[Full GC [PSYoungGen: 33152K->0K(557568K)] [ParOldGen: 1802524K->1835328K(2897920K)] 1835676K->1835328K(3455488K) [PSPermGen: 2993K->2993K(21504K)], 0.2019870 secs] [Times: user=2.74 sys=0.13, real=0.20 secs]
[GC [PSYoungGen: 492503K->33280K(647168K)] 2327831K->2327360K(3545088K), 0.0870810 secs] [Times: user=0.61 sys=0.92, real=0.09 secs]
[Full GC [PSYoungGen: 33280K->0K(647168K)] [ParOldGen: 2294080K->2326876K(3603968K)] 2327360K->2326876K(4251136K) [PSPermGen: 2993K->2993K(21504K)], 0.0512730 secs] [Times: user=0.09 sys=0.12, real=0.05 secs]

Heap
 PSYoungGen  total 647168K, used 340719K [0x00000006aaa80000, 0x00000006dd000000, 0x0000000800000000)
  eden space 613376K, 55% used [0x00000006aaa80000,0x00000006bf73bc10,0x00000006d0180000)
  from space 33792K, 0% used [0x00000006d2280000,0x00000006d2280000,0x00000006d4380000)
  to   space 33792K, 0% used [0x00000006d0180000,0x00000006d0180000,0x00000006d2280000)
 ParOldGen   total 3603968K, used 2326876K [0x0000000400000000, 0x00000004dbf80000, 0x00000006aaa80000)
  object space 3603968K, 64% used [0x0000000400000000,0x000000048e0572d8,0x00000004dbf80000)
 PSPermGen   total 21504K, used 3488K [0x00000003f5a00000, 0x00000003f6f00000, 0x0000000400000000)
  object space 21504K, 16% used [0x00000003f5a00000,0x00000003f5d68070,0x00000003f6f00000)
Heap
 PSYoungGen  total 4893696K, used 2840362K [0x00000006aaa80000, 0x0000000800000000, 0x0000000800000000)
  eden space 4194816K, 67% used [0x00000006aaa80000,0x000000075804a920,0x00000007aab00000)
  from space 698880K, 0% used [0x00000007d5580000,0x00000007d5580000,0x0000000800000000)
  to   space 698880K, 0% used [0x00000007aab00000,0x00000007aab00000,0x00000007d5580000)
 ParOldGen   total 11185152K, used 0K [0x00000003fff80000, 0x00000006aaa80000, 0x00000006aaa80000)
  object space 11185152K, 0% used [0x00000003fff80000,0x00000003fff80000,0x00000006aaa80000)
 PSPermGen   total 21504K, used 3489K [0x00000003f5980000, 0x00000003f6e80000, 0x00000003fff80000)
  object space 21504K, 16% used [0x00000003f5980000,0x00000003f5ce8400,0x00000003f6e80000)

访问内存需要CPU时间。访问更多内存不仅会线性增加CPU时间,而且可能会增加缓存压力,从而增加未命中率,从而超级线性地增加CPU时间

使用
perf stat java-jar…
运行程序以查看缓存未命中的数量。看



图像来源: “系统性能:企业与云平装本”,Brendan Gregg,ISBN:978-0133390094


由于初始堆大小也会影响eden空间大小,并且较小的eden空间会触发GC,因此这可能会导致更紧凑的堆,从而对缓存更友好(堆中没有临时启动对象)

要减少两次运行之间的差异数量,请尝试将两次运行的初始和最大年轻代大小设置为相同的值,以便只有旧代大小不同。这可能会导致同样的表现

顺便说一句:您也可以尝试用巨大的页面启动JVM,它可能(您需要测量!)通过进一步减少TLB未命中而为您带来几%的额外性能

未来读者注意:限制新一代的大小并不一定会使JVM更快,它只会触发一个GC,使@Peng的特定工作负载更快。

启动后手动触发GC也会产生同样的效果。

您是否有任何关于两次运行期间(1GB vs 16GB Xms)获得的分页/插入量的信息?“没有报告任何GC活动”似乎可疑;它表示程序的所有数据都保留在堆的“eden”部分。任何可能需要16GB堆的东西似乎都至少涉及一些小集合。除了@BrunoReis建议的页面错误之外,我还将研究交换统计数据和驻留集大小(RSS)。我可以想象一种可能的情况,线程本地分配块被分散开来,导致内存子系统需要更多的工作,但是(1)70线程似乎太低,这不是一个真正的问题,以及(2)我无法想象这会导致3倍的速度减慢,除非你正在遭受分页的痛苦。这就足够了还是你还需要更多?我关于没有gc活动的声明