8291878: NMT: Malloc limits

Reviewed-by: kvn, shade
This commit is contained in:
Thomas Stuefe 2022-08-24 07:58:54 +00:00
parent ad2e0c4df0
commit fa5cc4cc8e
9 changed files with 475 additions and 7 deletions

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2022 SAP SE. 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
@ -23,6 +24,8 @@
*/
#include "precompiled.hpp"
#include "logging/log.hpp"
#include "runtime/arguments.hpp"
#include "runtime/os.hpp"
#include "runtime/safefetch.hpp"
#include "services/mallocHeader.inline.hpp"
@ -31,10 +34,13 @@
#include "services/memTracker.hpp"
#include "utilities/debug.hpp"
#include "utilities/ostream.hpp"
#include "utilities/vmError.hpp"
#include "jvm_io.h"
size_t MallocMemorySummary::_snapshot[CALC_OBJ_SIZE_IN_TYPE(MallocMemorySnapshot, size_t)];
size_t MallocMemorySummary::_limits_per_category[mt_number_of_types] = { 0 };
size_t MallocMemorySummary::_total_limit = 0;
#ifdef ASSERT
void MemoryCounter::update_peak_count(size_t count) {
@ -88,6 +94,59 @@ void MallocMemorySummary::initialize() {
assert(sizeof(_snapshot) >= sizeof(MallocMemorySnapshot), "Sanity Check");
// Uses placement new operator to initialize static area.
::new ((void*)_snapshot)MallocMemorySnapshot();
initialize_limit_handling();
}
void MallocMemorySummary::initialize_limit_handling() {
// Initialize limit handling.
Arguments::parse_malloc_limits(&_total_limit, _limits_per_category);
if (_total_limit > 0) {
log_info(nmt)("MallocLimit: total limit: " SIZE_FORMAT "%s",
byte_size_in_proper_unit(_total_limit),
proper_unit_for_byte_size(_total_limit));
} else {
for (int i = 0; i < mt_number_of_types; i ++) {
size_t catlim = _limits_per_category[i];
if (catlim > 0) {
log_info(nmt)("MallocLimit: category \"%s\" limit: " SIZE_FORMAT "%s",
NMTUtil::flag_to_name((MEMFLAGS)i),
byte_size_in_proper_unit(catlim),
proper_unit_for_byte_size(catlim));
}
}
}
}
void MallocMemorySummary::total_limit_reached(size_t size, size_t limit) {
// Assert in both debug and release, but allow error reporting to malloc beyond limits.
if (!VMError::is_error_reported()) {
fatal("MallocLimit: reached limit (size: " SIZE_FORMAT ", limit: " SIZE_FORMAT ") ",
size, limit);
}
}
void MallocMemorySummary::category_limit_reached(size_t size, size_t limit, MEMFLAGS flag) {
// Assert in both debug and release, but allow error reporting to malloc beyond limits.
if (!VMError::is_error_reported()) {
fatal("MallocLimit: category \"%s\" reached limit (size: " SIZE_FORMAT ", limit: " SIZE_FORMAT ") ",
NMTUtil::flag_to_name(flag), size, limit);
}
}
void MallocMemorySummary::print_limits(outputStream* st) {
if (_total_limit != 0) {
st->print("MallocLimit: " SIZE_FORMAT, _total_limit);
} else {
bool first = true;
for (int i = 0; i < mt_number_of_types; i ++) {
if (_limits_per_category[i] > 0) {
st->print("%s%s:" SIZE_FORMAT, (first ? "MallocLimit: " : ", "),
NMTUtil::flag_to_name((MEMFLAGS)i), _limits_per_category[i]);
first = false;
}
}
}
}
bool MallocTracker::initialize(NMT_TrackingLevel level) {