确定一行代码中分配的内存量

Determine the amount of memory being allocated in a line of code

我对性能测试比较陌生,正在尝试确定每行代码分配了多少内存。我尝试将 MemoryMXBean 应用于问题,但得到的结果毫无意义。

我在代码行之前拍摄堆使用情况的快照,然后在代码行之后拍摄快照,最后我存储堆使用量增加时的差异 (假设垃圾收集器 运行 如果它减少了); getSnapshot() 方法来自我的测试代码 运行 ,用于重置计数器并打印结果。然而,这个测试告诉我,我们每行分配超过 20 mb,即使在不进行任何分配的行上也是如此。如果我采用中位数而不是平均值,那么我仍然会胡说八道,告诉我我们每行分配 47 MB​​。

我如何确定在一行代码中分配了多少内存,and/or 我在使用 MemoryMXBean 时做错了什么?

private static final MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();

private static final Map<Line, Tuple> lineMap;

static {
  Map<Line, Tuple> map = new EnumMap<Line, Tuple>(Line.class);
  for(Line line : Line.values()) {
    map.put(line, new Tuple());
  }
  lineMap = map;
}

public enum Line {
  line01,
  line02,
  line03,
  ...
}

public static Map<String, Long> getSnapshot() {
  Map<String, Long> returnVal = new HashMap<>();
  for(Map.Entry<Line, Tuple> entry : lineMap.entrySet()) {
    if(entry.getValue().count.get() > 0) {
      returnVal.put(entry.getKey().toString(), entry.getValue().memory.getAndSet(0) / entry.getValue().count.getAndSet(0));
    } else {
      entry.getValue().memory.set(0);
    }
  }
  return returnVal;
}

private static class Tuple {
  public final AtomicLong memory = new AtomicLong();
  public final AtomicLong count = new AtomicLong();
}

private static void update(Line line, long value) {
  long finish = memBean.getHeapMemoryUsage().getUsed();

  // ignore if the gc ran
  if(finish > value) {
    Tuple tuple = lineMap.get(line);
    tuple.memory.addAndGet(finish - value);
    tuple.count.incrementAndGet();
  }
}

public void codeIamTesting {
  long start = memBean.getHeapMemoryUsage().getUsed();
  // line1
  update(Line.line01, start);
}

当我禁用线程本地分配缓冲区(命令行参数 -XX:-UseTLAB)时,我得到了合理的结果 - memBean.getHeapMemoryUsage().getUsed() 调用为结果增加了一些开销,但很容易确定什么这个开销是(在我的例子中是 240 字节)并从数据中减去它。似乎在使用 -XX:+UseTLAB(默认设置)时,getUsed() 快照仅在分配新缓冲区时发生变化,导致大多数分配似乎使用零字节堆,而少数分配使用几兆字节堆。我还使用 -XX:+UseParallelGC 来减少使用 -XX:+UseG1GC

时的抖动量