测量垃圾收集时间的阻塞部分

时间:2017-07-08 23:07:36

标签: java multithreading performance garbage-collection performance-testing

Java的垃圾收集器(GC)并不总是停止主线程。它可能会阻塞所有线程,或者只是并行运行而不会暂停其他线程。

我可以通过使用来衡量垃圾收集总时间  程序结束时garbageCollectorMXBean.getCollectionTime();,或者使用-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -verbose:gc运行VM。

但是,我想测量主线程被阻塞(即暂停)的GC部分,以便我可以测量主线程运行的确切时间。是否可以测量它?

4 个答案:

答案 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)而导致主线程未运行的总时间。但是,这不会因为被其他应用程序线程阻塞而导致主线程暂停。