2017-10-06 170 views
3

我想跟进这篇博客中的一些技巧https://www.elastic.co/blog/a-heap-of-trouble#ref5,它讨论了调整一个Java堆的好处,以便(a)可以使用压缩指针(对于32GB以下的堆)和(b)以便堆驻留在地址0在内存中。本文详细介绍了压缩指针如何更有效地利用堆空间,并解释了当堆存放在地址0时,这减少了解析指针地址所需的算术量。最后,文章说,如果我使用JVM选项-XX:+UnlockDiagnosticVMOptions - XX:+PrintCompressedOopsMode我会看到日志输出要么是这样的:如何确定Java堆是否使用压缩指针以及是否驻留在内存中的地址0?

heap address: 0x000000011be00000, size: 27648 MB, zero based Compressed Oops

这表明从零开始压缩哎呀启用,或输出这样

heap address: 0x0000000118400000, size: 28672 MB, Compressed Oops with base: 0x00000001183ff000

这表明堆开始于非零的地址,因此需要前述的算术处理增加量。

但是,当我尝试这些选项并通过我的应用程序(Elastic Search)日志目录grep'd时,我找不到这样的消息。如果任何人都可以告诉我如何强制记录零基(或不是零)的压缩指针的细节,我将非常感激。

解决方案:

伟大的答案。我接受了@ apangin的,我裹着他在shell脚本提供的Java程序,只要你有java的..可以运行,你应该如果你正在寻找Java堆!这里是脚本:https://github.com/buildlackey/scripts/blob/master/verify_compressed_pointers_from_zero_offset.sh

+0

请注意,在这两种情况下,堆不会从零开始。但在第一种情况下,起始地址和堆大小的总和低于32GiB阈值,这允许基于零的寻址。但为什么这个问题标签为“垃圾收集”? – Holger

+0

如果我的回答没有帮助你,请提供有关您的操作系统和ES版本的信息。 – Ivan

+0

哇..很好的答案。我将在明天审查并尝试这些建议。作为对@Holger的回应,标记垃圾收集的原因是因为我们试图优化堆大小的设置以及其他垃圾收集相关的调整..认为这个话题与任何其他调整GC相关。 /日Thnx –

回答

3

HotSpot Serviceability Agent即使不需要额外的命令行标志,也可以在正在运行的JVM进程上显示它。

以目标Java进程ID作为参数运行以下程序。

import sun.jvm.hotspot.runtime.VM; 
import sun.jvm.hotspot.tools.Tool; 

public class CompressedOopsInfo extends Tool { 

    @Override 
    public void run() { 
     VM vm = VM.getVM(); 
     System.out.println("CompressedOops = " + vm.isCompressedOopsEnabled()); 
     System.out.println("CompressedClassPointers = " + vm.isCompressedKlassPointersEnabled()); 
     System.out.println("OOP base = 0x" + Long.toHexString(vm.getDebugger().getNarrowOopBase())); 
     System.out.println("OOP shift = " + vm.getDebugger().getNarrowOopShift()); 
    } 

    public static void main(String[] args) { 
     new CompressedOopsInfo().execute(args); 
    } 
} 

在JDK 9之前,这需要在类路径中包含${JDK_HOME}/lib/sa-jdi.jar。程序需要在与运行目标进程相同的JVM版本下运行。

1

但是,当我尝试这些选项并通过我的应用程序的(Elastic Search)日志目录grep'd时,我找不到这样的消息。

可能是因为它只记录应用程序消息到该目录。您还需要将JVM输出记录到文件中,或者检查标准输出或标准错误消息。

1

假设您正在使用版本为5.x及更高版本的Linux和ES。

的最有效的方法来收集整个集群的信息是使用the nodes info API

卷曲-XGET “http://localhost:9200/_nodes/jvm?filter_path=nodes * JVM。using_compressed_ordinary_object_pointers”

{ “节点”:{ “ - jYDCxbpT2SBKc4dTfOYsA”:{ “JVM”:{ “using_compressed_ordinary_object_pointers”: “真正的”}}}}

相同的信息被记录到主日志 - /var/log/elasticsearch/elasticsearch.log

[2017-10-06T23:03:15223] [INFO] [oeeNodeEnvironment] [-jYDCxb] 堆大小[1.9GB],压缩普通对象指针[true]

如果您对真正的JVM输出感兴趣,那么您必须知道,默认情况下,JVM会将其消息写入标准输出,并且在Linux发行版中,此输出默认情况下会配置为重定向到journalctl。所以你有两个选择。第一个是读journalctl:

须藤journalctl -u elasticsearch.service

精细克拉斯基:0x0000000000000000,精细克拉斯移:3 压缩类空间大小:1073741824地址:0x0000000100000000 REQ的地址: 0x0000000100000000

但有时journalctl默认是关闭的,你必须通过从ES命令行参数--quite参数来改变在守护程序配置/usr/lib/systemd/system/elasticsearch.service此设置。第二种方法是最简单的和跨平台 - 重定向JVM消息给特定的GC日志输出:

-XX:+ UnlockDiagnosticVMOptions -XX:+ PrintCompressedOopsMode -Xloggc:/tmp/vm.log

现在你可以看到所有的GC相关的输出在/tmp/vm.log

相关问题