Java 如何在Windows7中监控JVM对大内存页的使用?

Java 如何在Windows7中监控JVM对大内存页的使用?,java,windows,memory-management,Java,Windows,Memory Management,我试图衡量在Windows7热点JVM中使用大内存页的性能增益。为了做到这一点,我需要监控JVM内存使用情况,以确保实际使用了大页面。不幸的是,我找不到实现这一目标的方法。以下是我所做的设置和试验的说明: 环境设置 我正在使用64位Windows7终极版进行测试。如中所述,已启用“在内存中锁定页面”Windows安全策略。我还验证了通过运行java版本命令启用大页面功能,如下所示: java -XX:+UseLargePages -version 在这里,我得到了以下结果,这表明启用了大页面功

我试图衡量在Windows7热点JVM中使用大内存页的性能增益。为了做到这一点,我需要监控JVM内存使用情况,以确保实际使用了大页面。不幸的是,我找不到实现这一目标的方法。以下是我所做的设置和试验的说明:

环境设置

我正在使用64位Windows7终极版进行测试。如中所述,已启用“在内存中锁定页面”Windows安全策略。我还验证了通过运行java版本命令启用大页面功能,如下所示:

java -XX:+UseLargePages -version
在这里,我得到了以下结果,这表明启用了大页面功能:

java version "1.7.0_60"
Java(TM) SE Runtime Environment (build 1.7.0_60-b19)
Java HotSpot(TM) 64-Bit Server VM (build 24.60-b09, mixed mode)
我在所有的试验中都使用了这个示例Java程序来消耗Java堆的所有可用内存:

public class InfinteStringHashmap {
public static void main(String[] args) throws Exception{
    Map<Long, String> map = new HashMap<Long, String>();

    for(long i=1; true; i++){
        StringBuilder sb = new StringBuilder();
        for(long j=0;j<i;j++) sb.append(" ");
        map.put(i, sb.toString());

        if(i % 1000 == 0){
            System.out.print(".");
            Thread.sleep(1000);
        }
    }
  }
}
我还尝试了其他堆大小,小到12MB,大到10GB。请注意,我在重新启动机器后立即运行测试应用程序,以确保我的可用RAM内存没有碎片

监控内存的尝试失败

为了验证是否使用了大内存页,我尝试了:

  • 来自Windows系统内部,其中有一个用于大型页面的特定字段。无论我如何更改堆大小,它都不会显示大内存页的使用情况。为了验证这一点,我尝试了MSDN中的示例来缩小可能性。它工作得非常好(它从Insided代码中打印2MB页面大小)。“冲压图”工具不会显示任何内容
  • 使用中建议的代码打印Java进程使用的页面大小。它始终打印4096(Windows上的默认页面大小)。为了验证这一点,我在Linux版本的Hotspot JVM上尝试了大型页面,如中所述,并且成功了。但是,打印页面大小不起作用(它一直打印4096)
  • 显示特定进程的虚拟内存统计信息的工具。“-o”选项应该显示进程使用的VM类型、使用的页面数量以及每种类型占用的VM的总大小,这些可以用来推断是否使用大页面。不幸的是,当我设置JVM UseLargePages选项时,该命令失败,错误代码为24
  • 工具不会更新已查找的内存列
  • 简单的监视工具(如TaskManager和Perfmon)不提供有关大型页面的详细信息
  • 编辑:我尝试了评论中建议的以下工具:

  • Java任务控制器:不提供页面大小信息

  • Process Explorer:同上


  • 是否可以在Windows中测量进程的页面大小或监视大内存页面的使用情况???

    我不确定这是否是您想要的。
    但是(Process Explorer)可能会有所帮助。这没什么特别的。只是一个更高级的Windows7任务管理器

    另外,在以后的JavaJDK下载中,有一个叫做


    祝你好运

    我认为你的测试方法不合适。要优化TLB,请使用大内存页:

    A Translation-Lookaside Buffer (TLB) is a page translation cache that holds the most-recently used virtual-to-physical address translations. TLB is a scarce system resource. A TLB miss can be costly as the processor must then read from the hierarchical page table, which may require multiple memory accesses. By using bigger page size, a single TLB entry can represent larger memory range. There will be less pressure on TLB and memory-intensive applications may have better performance.
    
    您可以使用[JVisualVM]来评测应用程序。但在测试中,您会创建新对象。我不是这里的专家,但为了让mz理解TBL,您应该将数据从内存加载到应该在缓冲区中的结构。如果没有,我就要上船了


    从理论上讲,测量恒定操作数的时间的测试应该足以看到VM参数的影响

    LMP似乎是一个特定分配的特征,而不是整个过程的特征()。跟踪使用和未使用LMP的分配可能不可行


    更新:尝试将系统调用监视器附加到进程。您可以查看是否使用正确的参数调用VirtualAlloc。

    我已经尝试了JMC。不幸的是,它没有提供关于所用页面大小的信息。测量使用大内存页面(LMP)的性能增益是我的最终目标。目前,我正在努力确保我实际使用它们。理想情况下,当使用LMP时,我创建的所有对象都应该保存在非堆内存中,并且应该防止调出。一旦我确定使用LMP,您建议的测试就是衡量性能增益的正确方法。JVM不能混合使用大页面和小页面。即使您提供了适当的“大页面”选项“()。您能详细介绍一下附加系统调用监视器吗?我怀疑JVM使用了大页面作为堆。在Linux上,我会使用strace。我知道在Windows上有一个系统调用监视器是procmon,但它只记录文件、注册表和线程/进程,而不记录内存。另一个选择似乎是Windows性能记录器,但我从未亲自使用过。我确信还有更多的工具。我对此也很感兴趣-server-XX:+UseLargePages-XX:+PrintFinalFlags显示UseLargePages:=false(为什么?),并且所有堆内存仅在私有工作集中这一事实证实了这种情况。为运行JVM的用户启用了在内存中锁定页面的功能,重启后最多可释放12 GB RAM。
    A Translation-Lookaside Buffer (TLB) is a page translation cache that holds the most-recently used virtual-to-physical address translations. TLB is a scarce system resource. A TLB miss can be costly as the processor must then read from the hierarchical page table, which may require multiple memory accesses. By using bigger page size, a single TLB entry can represent larger memory range. There will be less pressure on TLB and memory-intensive applications may have better performance.