[英]Why does running a single threaded Java program result in many cores active?
I was benchmarking the total delay casting to datatype from Object
will have.我正在对从
Object
转换为数据类型的总延迟进行基准测试。 But I encountered a very weird behavior of a Java collection, in this case, a List
.但是我遇到了 Java 集合的一个非常奇怪的行为,在本例中为
List
。
List<Long> data = new ArrayList<>();
int SIZE = 50_000_000;
long currentTime = System.currentTimeMillis();
for (int i = 0; i < SIZE; i++) {
data.add(currentTime++);
}
When running the above code the CPU Utilization on my Intel i5 8250u (4 cores) the CPU utilization was 100% running on IntelliJ Idea.在我的Intel i5 8250u (4 核)上运行上述代码时,CPU 利用率在 IntelliJ Idea 上为 100%。 So I thought it could be because of IntelliJ, hence I move the code to Azure VM (running CentOS 7.4) having 20 Cores and to my surprise, this piece of code ended consuming 1500% CPU (result from
top
command) which is 15 cores.所以我认为这可能是因为 IntelliJ,因此我将代码移动到具有 20 个内核的 Azure VM(运行 CentOS 7.4),令我惊讶的是,这段代码最终消耗了1500% CPU(来自
top
命令的结果),即 15 个内核.
What I'm not able to understand is this: How can a single-threaded Java program code consume more than 1 core?我无法理解的是:单线程 Java 程序代码如何消耗 1 个以上的内核?
EDIT:
编辑:
Steps to Reproduce:重现步骤:
Run the above code.运行上面的代码。
Machine Configuration:机器配置:
Laptop: 4 Cores 16Gb RAM, Oracle Java 1.8_161笔记本电脑:4 核 16Gb RAM,Oracle Java 1.8_161
Azure VM: 20 Cores 148GB RAM, Oracle Java 1.8_161 Azure VM:20 核 148GB RAM,Oracle Java 1.8_161
Output From JVisualVM on Laptop:笔记本电脑上 JVisualVM 的输出:
Your test does nothing but allocating memory.您的测试除了分配内存之外什么都不做。 So it quickly exhausts initial heap memory, causing Full GC to run.
所以它很快耗尽了初始堆内存,导致 Full GC 运行。 The heap then increases, but it gets filled quickly again, causing another Full GC, etc.
然后堆增加,但它又很快被填满,导致另一个 Full GC,等等。
$ java -XX:+PrintGC Test
[GC (Allocation Failure) 27648K->20757K(104448K), 0.0296779 secs]
[GC (Allocation Failure) 48405K->40538K(132096K), 0.0293287 secs]
[GC (Allocation Failure) 83084K->82453K(138752K), 0.0615143 secs]
[Full GC (Ergonomics) 82453K->75113K(225792K), 0.5392036 secs]
[GC (Allocation Failure) 124981K->139346K(254464K), 0.0563272 secs]
[Full GC (Ergonomics) 139346K->112504K(353792K), 0.5240216 secs]
[GC (Allocation Failure) 185709K->208841K(380416K), 0.0864858 secs]
[Full GC (Ergonomics) 208841K->168513K(512512K), 0.9035611 secs]
...
So, what you observe is a series of long Full GC cycles.因此,您观察到的是一系列长的 Full GC 周期。 The default garbage collector in JDK 8 is Parallel, with the number of parallel GC threads equal to the number of CPUs.
JDK 8 中默认的垃圾收集器是 Parallel,并行 GC 线程的数量等于 CPU 的数量。
If you run async-profiler in threaded mode ( -t
), you'll find that almost all CPU time is spent running garbage collection in multiple threads.如果您以线程模式 (
-t
) 运行async-profiler ,您会发现几乎所有 CPU 时间都用于在多个线程中运行垃圾收集。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.