8320061: [nmt] Multiple issues with peak accounting

Reviewed-by: jsjolen, mbaesken
This commit is contained in:
Thomas Stuefe 2023-11-28 17:48:54 +00:00
parent adad132028
commit dc256fbc64
15 changed files with 559 additions and 305 deletions

View File

@ -55,7 +55,7 @@ void MemReporterBase::print_total(size_t reserved, size_t committed, size_t peak
output()->print("reserved=" SIZE_FORMAT "%s, committed=" SIZE_FORMAT "%s",
amount_in_current_scale(reserved), scale, amount_in_current_scale(committed), scale);
if (peak != 0) {
output()->print(", largest_committed=" SIZE_FORMAT "%s", amount_in_current_scale(peak), scale);
output()->print(", peak=" SIZE_FORMAT "%s", amount_in_current_scale(peak), scale);
}
}
@ -93,9 +93,15 @@ void MemReporterBase::print_malloc(const MemoryCounter* c, MEMFLAGS flag) const
}
void MemReporterBase::print_virtual_memory(size_t reserved, size_t committed, size_t peak) const {
outputStream* out = output();
const char* scale = current_scale();
output()->print("(mmap: reserved=" SIZE_FORMAT "%s, committed=" SIZE_FORMAT "%s, largest_committed=" SIZE_FORMAT "%s)",
amount_in_current_scale(reserved), scale, amount_in_current_scale(committed), scale, amount_in_current_scale(peak), scale);
out->print("(mmap: reserved=" SIZE_FORMAT "%s, committed=" SIZE_FORMAT "%s, ",
amount_in_current_scale(reserved), scale, amount_in_current_scale(committed), scale);
if (peak == committed) {
out->print_raw("at peak)");
} else {
out->print("peak=" SIZE_FORMAT "%s)", amount_in_current_scale(peak), scale);
}
}
void MemReporterBase::print_malloc_line(const MemoryCounter* c) const {
@ -204,74 +210,79 @@ void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag,
committed_amount += _malloc_snapshot->malloc_overhead();
}
if (amount_in_current_scale(reserved_amount) > 0) {
outputStream* out = output();
const char* scale = current_scale();
out->print("-%26s (", NMTUtil::flag_to_name(flag));
print_total(reserved_amount, committed_amount);
#if INCLUDE_CDS
if (flag == mtClassShared) {
size_t read_only_bytes = FileMapInfo::readonly_total();
output()->print(", readonly=" SIZE_FORMAT "%s",
amount_in_current_scale(read_only_bytes), scale);
}
#endif
out->print_cr(")");
// Omit printing if the current reserved value as well as all historical peaks (malloc, mmap committed, arena)
// fall below scale threshold
const size_t pk_vm = virtual_memory->peak_size();
const size_t pk_malloc = malloc_memory->malloc_peak_size();
const size_t pk_arena = malloc_memory->arena_peak_size();
if (flag == mtClass) {
// report class count
out->print_cr("%27s (classes #" SIZE_FORMAT ")",
" ", (_instance_class_count + _array_class_count));
out->print_cr("%27s ( instance classes #" SIZE_FORMAT ", array classes #" SIZE_FORMAT ")",
" ", _instance_class_count, _array_class_count);
} else if (flag == mtThread) {
if (ThreadStackTracker::track_as_vm()) {
const VirtualMemory* thread_stack_usage =
_vm_snapshot->by_type(mtThreadStack);
// report thread count
out->print_cr("%27s (threads #" SIZE_FORMAT ")", " ", ThreadStackTracker::thread_count());
out->print("%27s (stack: ", " ");
print_total(thread_stack_usage->reserved(), thread_stack_usage->committed(), thread_stack_usage->peak_size());
} else {
MallocMemory* thread_stack_memory = _malloc_snapshot->by_type(mtThreadStack);
const char* scale = current_scale();
// report thread count
out->print_cr("%27s (threads #" SIZE_FORMAT ")", " ", thread_stack_memory->malloc_count());
out->print("%27s (Stack: " SIZE_FORMAT "%s", " ",
amount_in_current_scale(thread_stack_memory->malloc_size()), scale);
}
out->print_cr(")");
}
// report malloc'd memory
if (amount_in_current_scale(malloc_memory->malloc_size()) > 0
|| amount_in_current_scale(malloc_memory->malloc_peak_size()) > 0) {
print_malloc_line(malloc_memory->malloc_counter());
}
if (amount_in_current_scale(virtual_memory->reserved()) > 0
DEBUG_ONLY(|| amount_in_current_scale(virtual_memory->peak_size()) > 0)) {
print_virtual_memory_line(virtual_memory->reserved(), virtual_memory->committed(), virtual_memory->peak_size());
}
if (amount_in_current_scale(malloc_memory->arena_size()) > 0
DEBUG_ONLY(|| amount_in_current_scale(malloc_memory->arena_peak_size()) > 0)) {
print_arena_line(malloc_memory->arena_counter());
}
if (flag == mtNMT &&
amount_in_current_scale(_malloc_snapshot->malloc_overhead()) > 0) {
out->print_cr("%27s (tracking overhead=" SIZE_FORMAT "%s)", " ",
amount_in_current_scale(_malloc_snapshot->malloc_overhead()), scale);
} else if (flag == mtClass) {
// Metadata information
report_metadata(Metaspace::NonClassType);
if (Metaspace::using_class_space()) {
report_metadata(Metaspace::ClassType);
}
}
out->print_cr(" ");
if (amount_in_current_scale(MAX4(reserved_amount, pk_vm, pk_malloc, pk_arena)) == 0) {
return;
}
outputStream* out = output();
const char* scale = current_scale();
out->print("-%26s (", NMTUtil::flag_to_name(flag));
print_total(reserved_amount, committed_amount);
#if INCLUDE_CDS
if (flag == mtClassShared) {
size_t read_only_bytes = FileMapInfo::readonly_total();
output()->print(", readonly=" SIZE_FORMAT "%s",
amount_in_current_scale(read_only_bytes), scale);
}
#endif
out->print_cr(")");
if (flag == mtClass) {
// report class count
out->print_cr("%27s (classes #" SIZE_FORMAT ")",
" ", (_instance_class_count + _array_class_count));
out->print_cr("%27s ( instance classes #" SIZE_FORMAT ", array classes #" SIZE_FORMAT ")",
" ", _instance_class_count, _array_class_count);
} else if (flag == mtThread) {
if (ThreadStackTracker::track_as_vm()) {
const VirtualMemory* thread_stack_usage =
_vm_snapshot->by_type(mtThreadStack);
// report thread count
out->print_cr("%27s (threads #" SIZE_FORMAT ")", " ", ThreadStackTracker::thread_count());
out->print("%27s (stack: ", " ");
print_total(thread_stack_usage->reserved(), thread_stack_usage->committed(), thread_stack_usage->peak_size());
} else {
MallocMemory* thread_stack_memory = _malloc_snapshot->by_type(mtThreadStack);
const char* scale = current_scale();
// report thread count
out->print_cr("%27s (threads #" SIZE_FORMAT ")", " ", thread_stack_memory->malloc_count());
out->print("%27s (Stack: " SIZE_FORMAT "%s", " ",
amount_in_current_scale(thread_stack_memory->malloc_size()), scale);
}
out->print_cr(")");
}
// report malloc'd memory
if (amount_in_current_scale(MAX2(malloc_memory->malloc_size(), pk_malloc)) > 0) {
print_malloc_line(malloc_memory->malloc_counter());
}
if (amount_in_current_scale(MAX2(virtual_memory->reserved(), pk_vm)) > 0) {
print_virtual_memory_line(virtual_memory->reserved(), virtual_memory->committed(), virtual_memory->peak_size());
}
if (amount_in_current_scale(MAX2(malloc_memory->arena_size(), pk_arena)) > 0) {
print_arena_line(malloc_memory->arena_counter());
}
if (flag == mtNMT &&
amount_in_current_scale(_malloc_snapshot->malloc_overhead()) > 0) {
out->print_cr("%27s (tracking overhead=" SIZE_FORMAT "%s)", " ",
amount_in_current_scale(_malloc_snapshot->malloc_overhead()), scale);
} else if (flag == mtClass) {
// Metadata information
report_metadata(Metaspace::NonClassType);
if (Metaspace::using_class_space()) {
report_metadata(Metaspace::ClassType);
}
}
out->print_cr(" ");
}
void MemSummaryReporter::report_metadata(Metaspace::MetadataType type) const {
@ -321,9 +332,8 @@ int MemDetailReporter::report_malloc_sites() {
const MallocSite* malloc_site;
int num_omitted = 0;
while ((malloc_site = malloc_itr.next()) != nullptr) {
// Don't report if site has never allocated less than one unit of whatever our scale is
if (scale() > 1 && amount_in_current_scale(malloc_site->size()) == 0
DEBUG_ONLY(&& amount_in_current_scale(malloc_site->peak_size()) == 0)) {
// Omit printing if the current value and the historic peak value both fall below the reporting scale threshold
if (amount_in_current_scale(MAX2(malloc_site->size(), malloc_site->peak_size())) == 0) {
num_omitted ++;
continue;
}
@ -353,8 +363,10 @@ int MemDetailReporter::report_virtual_memory_allocation_sites() {
if (virtual_memory_site->reserved() == 0) {
continue;
}
// Don't report if site has reserved less than one unit of whatever our scale is
if (scale() > 1 && amount_in_current_scale(virtual_memory_site->reserved()) == 0) {
// Omit printing if the current value and the historic peak value both fall below the
// reporting scale threshold
if (amount_in_current_scale(MAX2(virtual_memory_site->reserved(),
virtual_memory_site->peak_size())) == 0) {
num_omitted++;
continue;
}
@ -386,7 +398,16 @@ void MemDetailReporter::report_virtual_memory_map() {
void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion* reserved_rgn) {
assert(reserved_rgn != nullptr, "null pointer");
// Don't report if size is too small
// We don't bother about reporting peaks here.
// That is because peaks - in the context of virtual memory, peak of committed areas - make little sense
// when we report *by region*, which are identified by their location in memory. There is a philosophical
// question about identity here: e.g. a committed region that has been split into three regions by
// uncommitting a middle section of it, should that still count as "having peaked" before the split? If
// yes, which of the three new regions would be the spiritual successor? Rather than introducing more
// complexity, we avoid printing peaks altogether. Note that peaks should still be printed when reporting
// usage *by callsite*.
// Don't report if size is too small.
if (amount_in_current_scale(reserved_rgn->size()) == 0) return;
outputStream* out = output();

View File

@ -34,7 +34,6 @@
size_t VirtualMemorySummary::_snapshot[CALC_OBJ_SIZE_IN_TYPE(VirtualMemorySnapshot, size_t)];
#ifdef ASSERT
void VirtualMemory::update_peak(size_t size) {
size_t peak_sz = peak_size();
while (peak_sz < size) {
@ -46,7 +45,6 @@ void VirtualMemory::update_peak(size_t size) {
}
}
}
#endif // ASSERT
void VirtualMemorySummary::initialize() {
assert(sizeof(_snapshot) >= sizeof(VirtualMemorySnapshot), "Sanity Check");

View File

@ -42,21 +42,17 @@ class VirtualMemory {
size_t _reserved;
size_t _committed;
#ifdef ASSERT
volatile size_t _peak_size;
void update_peak(size_t size);
#endif // ASSERT
public:
VirtualMemory() : _reserved(0), _committed(0) {
DEBUG_ONLY(_peak_size = 0;)
}
VirtualMemory() : _reserved(0), _committed(0), _peak_size(0) {}
inline void reserve_memory(size_t sz) { _reserved += sz; }
inline void commit_memory (size_t sz) {
_committed += sz;
DEBUG_ONLY(update_peak(sz);)
assert(_committed <= _reserved, "Sanity check");
update_peak(_committed);
}
inline void release_memory (size_t sz) {
@ -72,7 +68,7 @@ class VirtualMemory {
inline size_t reserved() const { return _reserved; }
inline size_t committed() const { return _committed; }
inline size_t peak_size() const {
return DEBUG_ONLY(Atomic::load(&_peak_size)) NOT_DEBUG(0);
return Atomic::load(&_peak_size);
}
};
@ -85,10 +81,9 @@ class VirtualMemoryAllocationSite : public AllocationSite {
inline void reserve_memory(size_t sz) { _c.reserve_memory(sz); }
inline void commit_memory (size_t sz) { _c.commit_memory(sz); }
inline void uncommit_memory(size_t sz) { _c.uncommit_memory(sz); }
inline void release_memory(size_t sz) { _c.release_memory(sz); }
inline size_t reserved() const { return _c.reserved(); }
inline size_t committed() const { return _c.committed(); }
inline size_t peak_size() const { return _c.peak_size(); }
};
class VirtualMemorySummary;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2020, Red Hat, Inc. All rights reserved.
* Copyright (c) 2019, 2023, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,59 +31,81 @@
* java.management
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail HugeArenaTracking
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=summary HugeArenaTracking
*/
import java.util.Random;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.JDKToolFinder;
import jdk.test.lib.Utils;
import jdk.test.whitebox.WhiteBox;
public class HugeArenaTracking {
private static final long GB = 1024 * 1024 * 1024;
private static final long MB = 1024 * 1024;
private static final long GB = MB * 1024;
public static void main(String args[]) throws Exception {
OutputAnalyzer output;
final WhiteBox wb = WhiteBox.getWhiteBox();
// Grab my own PID
String pid = Long.toString(ProcessTools.getProcessId());
ProcessBuilder pb = new ProcessBuilder();
long arena1 = wb.NMTNewArena(1024);
long arena2 = wb.NMTNewArena(1024);
// Run 'jcmd <pid> VM.native_memory summary'
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=2KB, committed=2KB)");
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
new String[] { "scale=K" },
new String[] { "Test (reserved=2KB, committed=2KB)",
"(arena=2KB #2) (at peak)" });
Random rand = Utils.getRandomInstance();
// Allocate 2GB+ from arena
long total = 0;
while (total < 2 * GB) {
// Cap to 10M
long inc = rand.nextInt(10 * 1024 * 1024);
wb.NMTArenaMalloc(arena1, inc);
total += inc;
wb.NMTArenaMalloc(arena1, MB);
total += MB;
}
ProcessBuilder pb2 = new ProcessBuilder();
// Run 'jcmd <pid> VM.native_memory summary'
pb2.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=GB"});
output = new OutputAnalyzer(pb2.start());
output.shouldContain("Test (reserved=2GB, committed=2GB)");
// run a report at GB level. We should see our allocations; since they are rounded
// to GB, we expect an exact output match
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
new String[] { "scale=G" },
new String[] { "Test (reserved=2GB, committed=2GB)",
"(arena=2GB #2) (at peak)" });
// Repeat at MB level; we expect the same behavior
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
new String[] { "scale=M" },
new String[] { "Test (reserved=2048MB, committed=2048MB)",
"(arena=2048MB #2) (at peak)" });
wb.NMTFreeArena(arena1);
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=1KB, committed=1KB)");
// Repeat report at GB level. Reserved should be 0 now. Current usage is 1KB, since arena2 is left, but that
// is below GB scale threshold, so should show up as 0.
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
new String[] { "scale=G" },
new String[] { "Test (reserved=0GB, committed=0GB)",
"(arena=0GB #1) (peak=2GB #2)" });
// Same, for MB scale
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
new String[] { "scale=M" },
new String[] { "Test (reserved=0MB, committed=0MB)",
"(arena=0MB #1) (peak=2048MB #2)" });
// At KB level we should see the remaining 1KB. Note that we refrain from testing peak here
// since the number gets fuzzy: it depends on the size of the initially allocated chunk. At MB
// and GB scale, these differences don't matter.
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
new String[] { "scale=K" },
new String[] { "Test (reserved=1KB, committed=1KB)",
"(arena=1KB #1) (peak=" });
wb.NMTFreeArena(arena2);
output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Test (reserved");
// Everything free'd, current usage 0, peak should be preserved.
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
new String[] { "scale=G" },
new String[] { "Test (reserved=0GB, committed=0GB)",
"(arena=0GB #0) (peak=2GB #2)" });
}
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,23 +34,14 @@
*
*/
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.JDKToolFinder;
import jdk.test.whitebox.WhiteBox;
public class MallocRoundingReportTest {
private static long K = 1024;
public static void main(String args[]) throws Exception {
OutputAnalyzer output;
WhiteBox wb = WhiteBox.getWhiteBox();
// Grab my own PID
String pid = Long.toString(ProcessTools.getProcessId());
ProcessBuilder pb = new ProcessBuilder();
long[] additionalBytes = {0, 1, 512, 650};
long[] kByteSize = {1024, 2048};
long mallocd_total = 0;
@ -63,17 +55,18 @@ public class MallocRoundingReportTest {
mallocd_total = wb.NMTMalloc(curKB);
// Run 'jcmd <pid> VM.native_memory summary', check for expected output
// NMT does not track memory allocations less than 1KB, and rounds to the nearest KB
String expectedOut = ("Test (reserved=" + numKB + "KB, committed=" + numKB + "KB)");
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary" });
output = new OutputAnalyzer(pb.start());
output.shouldContain(expectedOut);
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
"Test (reserved=" + numKB + "KB, committed=" + numKB + "KB)",
"(malloc=" + numKB + "KB #1) (at peak)"
);
wb.NMTFree(mallocd_total);
// Run 'jcmd <pid> VM.native_memory summary', check for expected output
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary" });
output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Test (reserved=");
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
"Test (reserved=0KB, committed=0KB)",
"(malloc=0KB) (peak=" + numKB + "KB #1)"
);
}
}
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -130,7 +131,7 @@ public class MallocStressTest {
// All test memory allocated should be released
output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Test (reserved=");
output.shouldContain("Test (reserved=0KB, committed=0KB)");
// Verify that tracking level has not been downgraded
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "statistics"});

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,37 +33,34 @@
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTestType
*/
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.JDKToolFinder;
import jdk.test.whitebox.WhiteBox;
public class MallocTestType {
public static void main(String args[]) throws Exception {
OutputAnalyzer output;
WhiteBox wb = WhiteBox.getWhiteBox();
// Grab my own PID
String pid = Long.toString(ProcessTools.getProcessId());
ProcessBuilder pb = new ProcessBuilder();
// Use WB API to alloc and free with the mtTest type
long memAlloc3 = wb.NMTMalloc(128 * 1024);
long memAlloc2 = wb.NMTMalloc(256 * 1024);
wb.NMTFree(memAlloc3);
long memAlloc1 = wb.NMTMalloc(512 * 1024);
wb.NMTFree(memAlloc2);
long memAlloc3 = wb.NMTMalloc(128 * 1024); // current +128K #1 peak +128K #1
long memAlloc2 = wb.NMTMalloc(256 * 1024); // current +384K #2 peak +384K #2
// Run 'jcmd <pid> VM.native_memory summary'
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=512KB, committed=512KB)");
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
new String[]{"Test (reserved=384KB, committed=384KB)",
"(malloc=384KB #2) (at peak)"});
wb.NMTFree(memAlloc3); // current +256K #1 peak +384K #2
long memAlloc1 = wb.NMTMalloc(512 * 1024); // current +768K #2 peak +768K #2
wb.NMTFree(memAlloc2); // current +512K #1 peak +768K #2
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
new String[]{"Test (reserved=512KB, committed=512KB)",
"(malloc=512KB #1) (peak=768KB #2)"});
// Free the memory allocated by NMTAllocTest
wb.NMTFree(memAlloc1);
wb.NMTFree(memAlloc1); // current 0K #0 peak +768K #2
output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Test (reserved=");
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
new String[]{"Test (reserved=0KB, committed=0KB)",
"(malloc=0KB) (peak=768KB #2)"});
}
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,7 +32,7 @@
* java.management
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTrackingVerify
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=summary MallocTrackingVerify
*
*/
@ -53,11 +54,6 @@ public class MallocTrackingVerify {
public static WhiteBox wb = WhiteBox.getWhiteBox();
public static void main(String args[]) throws Exception {
OutputAnalyzer output;
// Grab my own PID
String pid = Long.toString(ProcessTools.getProcessId());
ProcessBuilder pb = new ProcessBuilder();
Random random = Utils.getRandomInstance();
// Allocate small amounts of memory with random pseudo call stack
@ -74,9 +70,10 @@ public class MallocTrackingVerify {
}
}
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary" });
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=4KB, committed=4KB)");
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
"Test (reserved=4KB, committed=4KB)",
"(malloc=4KB #" + mallocd_memory.size() + ") (at peak)"
);
// Free
for (MallocMemory mem : mallocd_memory) {
@ -84,10 +81,11 @@ public class MallocTrackingVerify {
}
// Run 'jcmd <pid> VM.native_memory summary', check for expected output
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid,
"VM.native_memory", "summary" });
output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Test (reserved=");
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
"Test (reserved=0KB, committed=0KB)",
"(malloc=0KB) (peak=4KB #" + + mallocd_memory.size() + ")"
);
}
static class MallocMemory {

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023 Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import jdk.test.lib.JDKToolFinder;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
public class NMTTestUtils {
public static OutputAnalyzer startJcmdVMNativeMemory(String... additional_args) throws Exception {
if (additional_args == null) {
additional_args = new String[] {};
}
String fullargs[] = new String[3 + additional_args.length];
fullargs[0] = JDKToolFinder.getJDKTool("jcmd");
fullargs[1] = Long.toString(ProcessTools.getProcessId());
fullargs[2] = "VM.native_memory";
System.arraycopy(additional_args, 0, fullargs, 3, additional_args.length);
ProcessBuilder pb = new ProcessBuilder();
pb.command(fullargs);
OutputAnalyzer output = new OutputAnalyzer(pb.start());
return output;
}
public static OutputAnalyzer startJcmdVMNativeMemoryDetail(String... additional_args) throws Exception {
return startJcmdVMNativeMemory("detail");
}
public static void runJcmdSummaryReportAndCheckOutput(String[] additional_args, String[] pattern, boolean verbose) throws Exception {
OutputAnalyzer output = startJcmdVMNativeMemory(additional_args);
output.stdoutShouldContainMultiLinePattern(pattern, true);
}
public static void runJcmdSummaryReportAndCheckOutput(String[] additional_args, String[] pattern) throws Exception {
runJcmdSummaryReportAndCheckOutput(additional_args, pattern, true);
}
public static void runJcmdSummaryReportAndCheckOutput(String... pattern) throws Exception {
runJcmdSummaryReportAndCheckOutput(null, pattern, true);
}
public static void checkReservedCommittedSummary(OutputAnalyzer output, long reservedKB, long committedKB, long peakKB) {
String peakString = (committedKB == peakKB) ? "at peak" : "peak=" + peakKB + "KB";
output.stdoutShouldContainMultiLinePattern(
"Test (reserved=" + reservedKB + "KB, committed=" + committedKB + "KB)",
"(mmap: reserved=" + reservedKB + "KB, committed=" + committedKB + "KB, " + peakString + ")"
);
}
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,12 +29,9 @@
* java.management
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedMallocTestType
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=summary ThreadedMallocTestType
*/
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.JDKToolFinder;
import jdk.test.whitebox.WhiteBox;
public class ThreadedMallocTestType {
@ -42,13 +40,8 @@ public class ThreadedMallocTestType {
public static long memAlloc3;
public static void main(String args[]) throws Exception {
OutputAnalyzer output;
final WhiteBox wb = WhiteBox.getWhiteBox();
// Grab my own PID
String pid = Long.toString(ProcessTools.getProcessId());
ProcessBuilder pb = new ProcessBuilder();
Thread allocThread = new Thread() {
public void run() {
// Alloc memory using the WB api
@ -66,9 +59,10 @@ public class ThreadedMallocTestType {
System.out.println("memAlloc3:"+memAlloc3);
// Run 'jcmd <pid> VM.native_memory summary'
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=896KB, committed=896KB)");
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
"Test (reserved=896KB, committed=896KB)",
"(malloc=896KB #3) (at peak)"
);
Thread freeThread = new Thread() {
public void run() {
@ -82,7 +76,9 @@ public class ThreadedMallocTestType {
freeThread.start();
freeThread.join();
output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Test (reserved=");
NMTTestUtils.runJcmdSummaryReportAndCheckOutput(
"Test (reserved=0KB, committed=0KB)",
"(malloc=0KB) (peak=896KB #3)"
);
}
}

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,9 +32,7 @@
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedVirtualAllocTestType
*/
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.JDKToolFinder;
import jdk.test.whitebox.WhiteBox;
public class ThreadedVirtualAllocTestType {
@ -45,8 +44,6 @@ public class ThreadedVirtualAllocTestType {
public static void main(String args[]) throws Exception {
OutputAnalyzer output;
String pid = Long.toString(ProcessTools.getProcessId());
ProcessBuilder pb = new ProcessBuilder();
Thread reserveThread = new Thread() {
public void run() {
@ -56,9 +53,8 @@ public class ThreadedVirtualAllocTestType {
reserveThread.start();
reserveThread.join();
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"});
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=512KB, committed=0KB)");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output,512, 0);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 512KB for Test");
Thread commitThread = new Thread() {
@ -69,8 +65,8 @@ public class ThreadedVirtualAllocTestType {
commitThread.start();
commitThread.join();
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=512KB, committed=128KB)");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output,512, 128);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB");
Thread uncommitThread = new Thread() {
@ -81,7 +77,8 @@ public class ThreadedVirtualAllocTestType {
uncommitThread.start();
uncommitThread.join();
output = new OutputAnalyzer(pb.start());
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output,512, 0);
output.shouldContain("Test (reserved=512KB, committed=0KB)");
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed");
@ -93,9 +90,18 @@ public class ThreadedVirtualAllocTestType {
releaseThread.start();
releaseThread.join();
output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Test (reserved=");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output,0, 0);
output.shouldNotContain("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved");
}
static long peakKB = 0;
public static void checkReservedCommittedSummary(OutputAnalyzer output, long reservedKB, long committedKB) {
if (committedKB > peakKB) {
peakKB = committedKB;
}
NMTTestUtils.checkReservedCommittedSummary(output, reservedKB, committedKB, peakKB);
}
}

View File

@ -36,9 +36,7 @@
*
*/
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.JDKToolFinder;
import jdk.test.lib.Platform;
import jdk.test.whitebox.WhiteBox;
@ -53,16 +51,10 @@ public class VirtualAllocCommitMerge {
long reserveSize = 4 * 1024 * 1024; // 4096KB
long addr;
String pid = Long.toString(ProcessTools.getProcessId());
ProcessBuilder pb = new ProcessBuilder();
// reserve
addr = wb.NMTReserveMemory(reserveSize);
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid,
"VM.native_memory", "detail" });
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "0KB");
output = NMTTestUtils.startJcmdVMNativeMemory("detail");
checkReservedCommittedSummary(output, 4096, 0);
checkReserved(output, addr, reserveSize, "4096KB");
long addrA = addr + (0 * commitSize);
@ -75,8 +67,8 @@ public class VirtualAllocCommitMerge {
// commit overlapping ABC, A, B, C
wb.NMTCommitMemory(addrA, 3 * commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "384KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 384);
checkReserved(output, addr, reserveSize, "4096KB");
checkCommitted(output, addrA, 3 * commitSize, "384KB");
@ -84,8 +76,8 @@ public class VirtualAllocCommitMerge {
wb.NMTCommitMemory(addrA, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "384KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 384);
checkReserved(output, addr, reserveSize, "4096KB");
checkCommitted(output, addrA, 3 * commitSize, "384KB");
@ -93,16 +85,16 @@ public class VirtualAllocCommitMerge {
wb.NMTCommitMemory(addrB, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "384KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 384);
checkReserved(output, addr, reserveSize, "4096KB");
checkCommitted(output, addrA, 3 * commitSize, "384KB");
wb.NMTCommitMemory(addrC, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "384KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 384);
checkReserved(output, addr, reserveSize, "4096KB");
checkCommitted(output, addrA, 3 * commitSize, "384KB");
@ -110,8 +102,8 @@ public class VirtualAllocCommitMerge {
// uncommit
wb.NMTUncommitMemory(addrA, 3 * commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "0KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 0);
}
// Test discontigous areas
@ -121,8 +113,8 @@ public class VirtualAllocCommitMerge {
wb.NMTCommitMemory(addrC, commitSize);
wb.NMTCommitMemory(addrE, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "384KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 384);
checkReserved(output, addr, reserveSize, "4096KB");
checkCommitted(output, addrA, commitSize, "128KB");
@ -134,8 +126,8 @@ public class VirtualAllocCommitMerge {
wb.NMTUncommitMemory(addrC, commitSize);
wb.NMTUncommitMemory(addrE, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "0KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 0);
}
// Test contiguous areas
@ -144,8 +136,8 @@ public class VirtualAllocCommitMerge {
wb.NMTCommitMemory(addrA, commitSize);
wb.NMTCommitMemory(addrB, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "256KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 256);
checkReserved(output, addr, reserveSize, "4096KB");
checkCommitted(output, addrA, 2 * commitSize, "256KB");
@ -154,8 +146,8 @@ public class VirtualAllocCommitMerge {
wb.NMTUncommitMemory(addrA, commitSize);
wb.NMTUncommitMemory(addrB, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "0KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 0);
}
{
@ -163,8 +155,8 @@ public class VirtualAllocCommitMerge {
wb.NMTCommitMemory(addrB, commitSize);
wb.NMTCommitMemory(addrA, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "256KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 256);
checkReserved(output, addr, reserveSize, "4096KB");
checkCommitted(output, addrA, 2 * commitSize, "256KB");
@ -173,8 +165,8 @@ public class VirtualAllocCommitMerge {
wb.NMTUncommitMemory(addrB, commitSize);
wb.NMTUncommitMemory(addrA, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "0KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 0);
}
{
@ -183,8 +175,8 @@ public class VirtualAllocCommitMerge {
wb.NMTCommitMemory(addrB, commitSize);
wb.NMTCommitMemory(addrC, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "384KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 384);
checkReserved(output, addr, reserveSize, "4096KB");
checkCommitted(output, addrA, 3 * commitSize, "384KB");
@ -194,8 +186,8 @@ public class VirtualAllocCommitMerge {
wb.NMTUncommitMemory(addrB, commitSize);
wb.NMTUncommitMemory(addrC, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "0KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 0);
}
{
@ -204,8 +196,8 @@ public class VirtualAllocCommitMerge {
wb.NMTCommitMemory(addrC, commitSize);
wb.NMTCommitMemory(addrB, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "384KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 384);
checkReserved(output, addr, reserveSize, "4096KB");
checkCommitted(output, addrA, 3 * commitSize, "384KB");
@ -215,8 +207,8 @@ public class VirtualAllocCommitMerge {
wb.NMTUncommitMemory(addrC, commitSize);
wb.NMTUncommitMemory(addrB, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "0KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 0);
}
{
@ -225,8 +217,8 @@ public class VirtualAllocCommitMerge {
wb.NMTCommitMemory(addrA, commitSize);
wb.NMTCommitMemory(addrC, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "384KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 384);
checkReserved(output, addr, reserveSize, "4096KB");
checkCommitted(output, addrA, 3 * commitSize, "384KB");
@ -236,8 +228,8 @@ public class VirtualAllocCommitMerge {
wb.NMTUncommitMemory(addrA, commitSize);
wb.NMTUncommitMemory(addrC, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "0KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 0);
}
{
@ -246,8 +238,8 @@ public class VirtualAllocCommitMerge {
wb.NMTCommitMemory(addrC, commitSize);
wb.NMTCommitMemory(addrA, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "384KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 384);
checkReserved(output, addr, reserveSize, "4096KB");
checkCommitted(output, addrA, 3 * commitSize, "384KB");
@ -257,8 +249,8 @@ public class VirtualAllocCommitMerge {
wb.NMTUncommitMemory(addrC, commitSize);
wb.NMTUncommitMemory(addrA, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "0KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 0);
}
{
@ -267,8 +259,8 @@ public class VirtualAllocCommitMerge {
wb.NMTCommitMemory(addrA, commitSize);
wb.NMTCommitMemory(addrB, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "384KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 384);
checkReserved(output, addr, reserveSize, "4096KB");
checkCommitted(output, addrA, 3 * commitSize, "384KB");
@ -278,8 +270,8 @@ public class VirtualAllocCommitMerge {
wb.NMTUncommitMemory(addrA, commitSize);
wb.NMTUncommitMemory(addrB, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "0KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 0);
}
{
@ -288,8 +280,8 @@ public class VirtualAllocCommitMerge {
wb.NMTCommitMemory(addrB, commitSize);
wb.NMTCommitMemory(addrA, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "384KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 384);
checkReserved(output, addr, reserveSize, "4096KB");
checkCommitted(output, addrA, 3 * commitSize, "384KB");
@ -299,20 +291,26 @@ public class VirtualAllocCommitMerge {
wb.NMTUncommitMemory(addrB, commitSize);
wb.NMTUncommitMemory(addrA, commitSize);
output = new OutputAnalyzer(pb.start());
checkReservedCommittedSummary(output, "4096KB", "0KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 0);
}
// release
wb.NMTReleaseMemory(addr, reserveSize);
output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Test (reserved=");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 0, 0);
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*"
+ Long.toHexString(addr + reserveSize) + "\\] reserved 4096KB for Test");
}
public static void checkReservedCommittedSummary(OutputAnalyzer output, String reservedString, String committedString) {
output.shouldContain("Test (reserved=" + reservedString + ", committed=" + committedString + ")");
// running peak counter
static long peakKB = 0;
public static void checkReservedCommittedSummary(OutputAnalyzer output, long reservedKB, long committedKB) {
if (committedKB > peakKB) {
peakKB = committedKB;
}
NMTTestUtils.checkReservedCommittedSummary(output, reservedKB, committedKB, peakKB);
}
public static void checkReserved(OutputAnalyzer output, long addr, long size, String sizeString) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,10 +33,7 @@
*
*/
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.JDKToolFinder;
import jdk.test.whitebox.WhiteBox;
public class VirtualAllocCommitUncommitRecommit {
@ -49,16 +46,10 @@ public class VirtualAllocCommitUncommitRecommit {
long reserveSize = 4 * 1024 * 1024; // 4096KB
long addr;
String pid = Long.toString(ProcessTools.getProcessId());
ProcessBuilder pb = new ProcessBuilder();
// reserve
addr = wb.NMTReserveMemory(reserveSize);
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid,
"VM.native_memory", "detail" });
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=4096KB, committed=0KB)");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 0);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*"
+ Long.toHexString(addr + reserveSize)
+ "\\] reserved 4096KB for Test");
@ -76,8 +67,8 @@ public class VirtualAllocCommitUncommitRecommit {
wb.NMTCommitMemory(addrC, commitSize);
wb.NMTCommitMemory(addrD, commitSize);
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=4096KB, committed=512KB)");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 512);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*"
+ Long.toHexString(addr + reserveSize)
@ -86,9 +77,8 @@ public class VirtualAllocCommitUncommitRecommit {
wb.NMTUncommitMemory(addrB, commitSize);
wb.NMTUncommitMemory(addrC, commitSize);
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=4096KB, committed=256KB)");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 256);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*"
+ Long.toHexString(addr + reserveSize)
+ "\\] reserved 4096KB for Test");
@ -97,8 +87,8 @@ public class VirtualAllocCommitUncommitRecommit {
wb.NMTCommitMemory(addrE, commitSize);
wb.NMTCommitMemory(addrF, commitSize);
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=4096KB, committed=512KB)");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 512);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*"
+ Long.toHexString(addr + reserveSize)
+ "\\] reserved 4096KB for Test");
@ -106,8 +96,8 @@ public class VirtualAllocCommitUncommitRecommit {
// uncommit A
wb.NMTUncommitMemory(addrA, commitSize);
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=4096KB, committed=384KB)");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 384);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*"
+ Long.toHexString(addr + reserveSize)
+ "\\] reserved 4096KB for Test");
@ -117,8 +107,8 @@ public class VirtualAllocCommitUncommitRecommit {
wb.NMTCommitMemory(addrB, commitSize);
wb.NMTCommitMemory(addrC, commitSize);
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=4096KB, committed=768KB)");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 768);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*"
+ Long.toHexString(addr + reserveSize)
+ "\\] reserved 4096KB for Test");
@ -131,17 +121,27 @@ public class VirtualAllocCommitUncommitRecommit {
wb.NMTUncommitMemory(addrE, commitSize);
wb.NMTUncommitMemory(addrF, commitSize);
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=4096KB, committed=0KB)");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 4096, 0);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*"
+ Long.toHexString(addr + reserveSize)
+ "\\] reserved 4096KB for Test");
// release
wb.NMTReleaseMemory(addr, reserveSize);
output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Test (reserved=");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 0, 0);
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*"
+ Long.toHexString(addr + reserveSize) + "\\] reserved 4096KB for Test");
}
// running peak counter
static long peakKB = 0;
public static void checkReservedCommittedSummary(OutputAnalyzer output, long reservedKB, long committedKB) {
if (committedKB > peakKB) {
peakKB = committedKB;
}
NMTTestUtils.checkReservedCommittedSummary(output, reservedKB, committedKB, peakKB);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,9 +32,7 @@
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail VirtualAllocTestType
*/
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.JDKToolFinder;
import jdk.test.whitebox.WhiteBox;
public class VirtualAllocTestType {
@ -44,36 +42,120 @@ public class VirtualAllocTestType {
OutputAnalyzer output;
long commitSize = 128 * 1024;
long reserveSize = 256 * 1024;
long addr;
long addr1, addr2;
String pid = Long.toString(ProcessTools.getProcessId());
ProcessBuilder pb = new ProcessBuilder();
String info = "start";
addr = wb.NMTReserveMemory(reserveSize);
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"});
try {
// ------
// Reserve first mapping
addr1 = wb.NMTReserveMemory(reserveSize);
info = "reserve 1: addr1=" + addr1;
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=256KB, committed=0KB)");
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 256KB for Test");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 256, 0);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + reserveSize) + "\\] reserved 256KB for Test");
wb.NMTCommitMemory(addr, commitSize);
// ------
// Reserve second mapping
addr2 = wb.NMTReserveMemory(reserveSize);
info = "reserve 2: addr2=" + addr2;
// If the second mapping happens to be adjacent to the first mapping, reserve another mapping and release the second mapping; for
// this test, we want to see two disjunct mappings.
if (addr2 == addr1 + reserveSize) {
long tmp = wb.NMTReserveMemory(reserveSize);
wb.NMTReleaseMemory(addr2, reserveSize);
addr2 = tmp;
}
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=256KB, committed=128KB)");
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB");
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 512, 0);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + reserveSize) + "\\] reserved 256KB for Test");
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr2) + " - 0x[0]*" + Long.toHexString(addr2 + reserveSize) + "\\] reserved 256KB for Test");
wb.NMTUncommitMemory(addr, commitSize);
// ------
// Now commit the first mapping
wb.NMTCommitMemory(addr1, commitSize);
info = "commit 1";
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 512, 128);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + reserveSize) + "\\] reserved 256KB for Test");
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + commitSize) + "\\] committed 128KB");
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr2) + " - 0x[0]*" + Long.toHexString(addr2 + reserveSize) + "\\] reserved 256KB for Test");
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=256KB, committed=0KB)");
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed");
// ------
// Now commit the second mapping
wb.NMTCommitMemory(addr2, commitSize);
info = "commit 2";
wb.NMTReleaseMemory(addr, reserveSize);
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 512, 256);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + reserveSize) + "\\] reserved 256KB for Test");
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + commitSize) + "\\] committed 128KB");
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr2) + " - 0x[0]*" + Long.toHexString(addr2 + reserveSize) + "\\] reserved 256KB for Test");
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr2) + " - 0x[0]*" + Long.toHexString(addr2 + commitSize) + "\\] committed 128KB");
output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Test (reserved=");
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved");
// ------
// Now uncommit the second mapping
wb.NMTUncommitMemory(addr2, commitSize);
info = "uncommit 2";
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 512, 128);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + reserveSize) + "\\] reserved 256KB for Test");
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + commitSize) + "\\] committed 128KB");
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr2) + " - 0x[0]*" + Long.toHexString(addr2 + reserveSize) + "\\] reserved 256KB for Test");
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr2) + " - 0x[0]*" + Long.toHexString(addr2 + commitSize) + "\\] committed 128KB");
// ------
// Now uncommit the first mapping
wb.NMTUncommitMemory(addr1, commitSize);
info = "uncommit 1";
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 512, 0);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + reserveSize) + "\\] reserved 256KB for Test");
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + commitSize) + "\\] committed 128KB");
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr2) + " - 0x[0]*" + Long.toHexString(addr2 + reserveSize) + "\\] reserved 256KB for Test");
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr2) + " - 0x[0]*" + Long.toHexString(addr2 + commitSize) + "\\] committed 128KB");
// ----------
// Release second mapping
wb.NMTReleaseMemory(addr2, reserveSize);
info = "release 2";
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 256, 0);
output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + reserveSize) + "\\] reserved 256KB for Test");
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + commitSize) + "\\] committed 128KB");
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr2) + " - 0x[0]*" + Long.toHexString(addr2 + reserveSize) + "\\] reserved 256KB for Test");
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr2) + " - 0x[0]*" + Long.toHexString(addr2 + commitSize) + "\\] committed 128KB");
// ----------
// Release first mapping
wb.NMTReleaseMemory(addr1, reserveSize);
info = "release 1";
output = NMTTestUtils.startJcmdVMNativeMemoryDetail();
checkReservedCommittedSummary(output, 0, 0);
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + reserveSize) + "\\] reserved 256KB for Test");
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr1) + " - 0x[0]*" + Long.toHexString(addr1 + commitSize) + "\\] committed 128KB");
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr2) + " - 0x[0]*" + Long.toHexString(addr2 + reserveSize) + "\\] reserved 256KB for Test");
output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr2) + " - 0x[0]*" + Long.toHexString(addr2 + commitSize) + "\\] committed 128KB");
} catch (Exception e) {
throw new RuntimeException(e.getMessage() + " (" + info + ")");
}
}
static long peakKB = 0;
public static void checkReservedCommittedSummary(OutputAnalyzer output, long reservedKB, long committedKB) {
if (committedKB > peakKB) {
peakKB = committedKB;
}
NMTTestUtils.checkReservedCommittedSummary(output, reservedKB, committedKB, peakKB);
}
}

View File

@ -621,6 +621,14 @@ public final class OutputAnalyzer {
return asLines(getOutput());
}
public List<String> stdoutAsLines() {
return asLines(getStdout());
}
public List<String> stderrAsLines() {
return asLines(getStderr());
}
private List<String> asLines(String buffer) {
return Arrays.asList(buffer.split("\\R"));
}
@ -786,4 +794,72 @@ public final class OutputAnalyzer {
return -1;
}
private void searchLinesForMultiLinePattern(String[] haystack, String[] needles, boolean verbose) {
if (needles.length == 0) {
return;
}
int firstNeedlePos = 0;
for (int i = 0; i < haystack.length; i++) {
if (verbose) {
System.out.println("" + i + ":" + haystack[i]);
}
if (haystack[i].contains(needles[0])) {
if (verbose) {
System.out.println("Matches pattern 0 (\"" + needles[0] + "\")");
}
firstNeedlePos = i;
break;
}
}
for (int i = 1; i < needles.length; i++) {
int haystackPos = firstNeedlePos + i;
if (haystackPos < haystack.length) {
if (verbose) {
System.out.println("" + haystackPos + ":" + haystack[haystackPos]);
}
if (haystack[haystackPos].contains(needles[i])) {
if (verbose) {
System.out.println("Matches pattern " + i + "(\"" + needles[i] + "\")");
}
} else {
String err = "First unmatched pattern: " + i + " (\"" + needles[i] + "\")";
if (!verbose) { // don't print twice
reportDiagnosticSummary();
}
throw new RuntimeException(err);
}
}
}
}
public void stdoutShouldContainMultiLinePattern(String[] needles, boolean verbose) {
String [] stdoutLines = stdoutAsLines().toArray(new String[0]);
searchLinesForMultiLinePattern(stdoutLines, needles, verbose);
}
public void stdoutShouldContainMultiLinePattern(String... needles) {
stdoutShouldContainMultiLinePattern(needles, true);
}
public void stderrShouldContainMultiLinePattern(String[] needles, boolean verbose) {
String [] stderrLines = stdoutAsLines().toArray(new String[0]);
searchLinesForMultiLinePattern(stderrLines, needles, verbose);
}
public void stderrShouldContainMultiLinePattern(String... needles) {
stderrShouldContainMultiLinePattern(needles, true);
}
public void shouldContainMultiLinePattern(String[] needles, boolean verbose) {
String [] lines = asLines().toArray(new String[0]);
searchLinesForMultiLinePattern(lines, needles, verbose);
}
public void shouldContainMultiLinePattern(String... needles) {
shouldContainMultiLinePattern(needles, true);
}
}