Java的垃圾收集器(GC)并不总是停止主线程。它可能会阻塞所有线程,或者只是并行运行而不会暂停其他线程。
我可以通过使用来衡量垃圾收集总时间
程序结束时garbageCollectorMXBean.getCollectionTime();
,或者使用-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -verbose:gc
运行VM。
但是,我想测量主线程被阻塞(即暂停)的GC部分,以便我可以测量主线程运行的确切时间。是否可以测量它?
答案 0 :(得分:3)
我猜你的问题归结为测量“主线程运行的确切时间”。为了了解这一点,您不需要测量垃圾收集器的阻塞时间。
线程运行的时间与其CPU时间相对应。如果你还想考虑等待I / O的时间,那么这种方法对你不起作用,但是垃圾收集器暂停你的线程的时间应该可以忽略不计。
我为你准备了一个简单的概念证明:
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.TimeUnit;
public class CpuTime
{
public static void main(String[] args) {
// We obtain the thread mx bean and check if it support CPU time measuring.
final ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
if (!threadMxBean.isThreadCpuTimeSupported())
throw new IllegalStateException("CPU time not supported on this platform");
// This is important because the default value is platform-dependent.
threadMxBean.setThreadCpuTimeEnabled(true);
// Now we start the measurement ...
final long threadId = Thread.currentThread().getId();
final long wallTimeStart = System.nanoTime();
final long cpuTimeStart = threadMxBean.getThreadCpuTime(Thread.currentThread().getId());
// ... and do stupid things to give the garbage collector some work.
for (int i = 0; i < 1_000_000_000; i++) {
Long l = new Long(i);
}
// Finally we measure the cpu and wall time.
final long wallTime = System.nanoTime() - wallTimeStart;
final long cpuTime = threadMxBean.getThreadCpuTime(threadId) - cpuTimeStart;
System.out.println("CPU time: " + TimeUnit.NANOSECONDS.toMillis(cpuTime));
System.out.println("Wall time: " + TimeUnit.NANOSECONDS.toMillis(wallTime));
}
}
请注意,这种方法需要进行一些调整以获得绝对精确的结果。但它应该让你开始。
答案 1 :(得分:2)
使用<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Title Page</title>
<!-- Normalize -->
<link type="text/css" rel="stylesheet" href="normalize/normalize.css"/>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<!-- Custom CSS -->
<link href="styles.css" rel="stylesheet" type="text/css">
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Titillium+Web:400,900" rel="stylesheet">
</head>
<body>
<br>
<!-- Nav Bar -->
<div class="pos-f-t">
<div class="collapse" id="navbarToggleExternalContent">
<div class="bg-transparent p-4">
<ul class="nav flex-column">
<li class="portfolio font-weight-bold">
<a class="nav-link active" href="portfolio.html">portfolio</a>
</li>
<li class="about font-weight-bold">
<a class="nav-link" href="#">about</a>
</li>
<li class="contact font-weight-bold">
<a class="nav-link" href="#">contact</a>
</li>
<li class="youtube">
<a class="nav-link text-danger font-weight-bold" href="#">YouTube Channel (comming soon!)</a>
</li>
</ul>
</div>
</div>
<nav class="navbar navbar-light bg-transparent">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggleExternalContent" aria-controls="navbarToggleExternalContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</nav>
</div>
<!-- /Nav Bar -->
<h1 class="lead">My Name</h1>
<p class="webdev">Web Developer</p>
<!-- jQuery first, then Tether, then Bootstrap JS. -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.js" integrity="sha256-tA8y0XqiwnpwmOIl3SGAcFl2RvxHjA8qp0+1uCGmRmg=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<script src="interact.js" type="text/javascript"></script>
</body>
</html>
和/或-XX:+PrintGCApplicationStoppedTime
答案 2 :(得分:1)
除了GC日志和MBean之外,还有JVM的perf计数器公开相关信息。
jcmd.exe PID PerfCounter.print | grep "sun.rt.safepointTime"
命令将显示JVM自启动以来处于Stop-the-World状态的累计经过时间。
答案 3 :(得分:0)
您可能需要查看jHiccup,https://www.azul.com/jhiccup/(免费和开源)。这可以衡量应用程序以外的所有内容对应用程序性能的影响。您可以使用此数据来计算由于JVM等效果(如GC)而导致主线程未运行的总时间。但是,这不会因为被其他应用程序线程阻塞而导致主线程暂停。