【问题标题】:Java memory benchmark [closed]Java内存基准[关闭]
【发布时间】:2023-04-05 11:59:02
【问题描述】:

我目前正在用 Java 开发自己的宠物项目,其中包含自定义数据结构。 为了测量性能,我选择了 Google Caliper 框架,但是为了测量数据结构的内存使用情况,我应该每次使用 VisuamVm(转储堆并等待计算对象保留大小)来测量它,以获得有效的结果。我想做某种“内存基准”测试。

所以,问题是:

是否有任何类似于 CaliperJunitBenchmarks 的 Java 框架允许进行测试以测量我的数据结构的内存消耗?

【问题讨论】:

    标签: java memory data-structures benchmarking microbenchmark


    【解决方案1】:

    此工具适合您。 Open JDK - Java Object Layout

    Sample examining HashMap

    $ java -jar jol-cli/target/jol-internals.jar java.util.HashMap
      Running 64-bit HotSpot VM.
      Using compressed references with 3-bit shift.
      Objects are 8 bytes aligned.
      Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
      Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
    
      java.util.HashMap object internals:
       OFFSET  SIZE       TYPE DESCRIPTION                    VALUE
        0     4            (object header)                01 00 00 00 (00000001 00000000    00000000 00000000)
        4     4            (object header)                00 00 00 00 (00000000 00000000 00000000 00000000)
        8     4            (object header)                0f 0f 3e e0 (00001111 00001111 00111110 11100000)
       12     4        Set AbstractMap.keySet             null
       16     4 Collection AbstractMap.values             null
       20     4        int HashMap.size                   0
       24     4        int HashMap.threshold              16
       28     4      float HashMap.loadFactor             0.75
       32     4        int HashMap.modCount               0
       36     4        int HashMap.hashSeed               0
       40     4    Entry[] HashMap.table                  []
       44     4        Set HashMap.entrySet               null
       Instance size: 48 bytes (estimated, add this JAR via -javaagent: to get accurate result)
       Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
    

    【讨论】:

      【解决方案2】:

      虽然我不知道有什么库可以做到这一点,但有比使用堆转储来测量内存使用情况更好的方法:您可以要求 JVM 使用 System.gc() 执行垃圾回收,然后使用查询堆使用情况Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory().

      【讨论】:

      • 谢谢,但据我所知,这不是测量对象精确尺寸的最佳方法。
      • 为什么不呢?您是要测量对象大小,还是要查找整个对象图的堆内存使用贡献?那不一样...
      • 我需要保留对象的大小。当我使用 VisuamVm 分析堆时,我发现很多对象不是从我的测试程序创建的(我从 IntelliJ 运行它),据我所知,使用 Runtime.getRuntime().totalMemory() 可能会得到无效结果- Runtime.getRuntime().freeMemory().
      【解决方案3】:

      内存基准包含两点:吞吐量片段。在这里,我认为您要做的是为这些环境选择更好的数据结构。对于这一点,我想你也需要这两点来衡量。

      在这里您可以使用OQL(对象查询语言)来查询此数据结构的使用情况。您可以使用 hprofMAT 来分析系统的堆上下文。

      为了解决您进行测试以测量内存消耗的问题,我建议以下步骤:

      1. 营造高效的环境
      2. 运行程序
      3. 重要的是,你可以转储你的堆Use JMX to make HPROF heap dumps right before and after a full GC
      4. 使用 MATVisualVM 分析 hprof

      【讨论】:

      • 谢谢!您能否推荐一些关于 Java 内存上下文中的吞吐量和片段的文章?我以前从未听说过这个术语。