提交 257eab1b 编写于 作者: H Hao Tang 提交者: Hao Tang

[MultiTenant] Print tenant ID in GC log of tenant triggerred GC

Summary: Print Tenant ID in GC log of tenant triggered GC

Test Plan: hotspot/test/multi-tenant/

Reviewed-by: luchsh, mmyxym

Issue: https://github.com/alibaba/dragonwell8/issues/102
上级 f91cbf28
......@@ -1306,7 +1306,12 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
{
GCTraceTime t(GCCauseString("Full GC", gc_cause()), G1Log::fine(), true, NULL, gc_tracer->gc_id());
GCCauseString cause_string("Full GC", gc_cause());
if (TenantHeapIsolation && !gc_cause_context().is_system()) {
cause_string.append(FormatBuffer<>(" (tenant-%ld)",
com_alibaba_tenant_TenantContainer::get_tenant_id(gc_cause_context()->tenant_container())));
}
GCTraceTime t(cause_string, G1Log::fine(), true, NULL, gc_tracer->gc_id());
TraceCollectorStats tcs(g1mm()->full_collection_counters());
TraceMemoryManagerStats tms(true /* fullGC */, gc_cause());
......@@ -2613,6 +2618,9 @@ void G1CollectedHeap::collect(GCCause::Cause cause) {
} else {
// Schedule a Full GC.
VM_G1CollectFull op(gc_count_before, full_gc_count_before, cause);
if (TenantHeapIsolation) {
op.set_allocation_context(AllocationContext::current());
}
VMThread::execute(&op);
}
}
......@@ -3992,6 +4000,10 @@ void G1CollectedHeap::log_gc_header() {
GCCauseString gc_cause_str = GCCauseString("GC pause", gc_cause())
.append(g1_policy()->gcs_are_young() ? "(young)" : "(mixed)")
.append(g1_policy()->during_initial_mark_pause() ? " (initial-mark)" : "");
if (TenantHeapIsolation && !gc_cause_context().is_system()) {
gc_cause_str.append(FormatBuffer<>(" (tenant-%ld)",
com_alibaba_tenant_TenantContainer::get_tenant_id(gc_cause_context()->tenant_container())));
}
gclog_or_tty->print("[%s", (const char*)gc_cause_str);
}
......
......@@ -1664,6 +1664,31 @@ public:
protected:
size_t _max_heap_capacity;
private:
// Context for on-going GC cause
AllocationContext_t _gc_cause_context;
public:
void set_gc_cause_context(AllocationContext_t context) { _gc_cause_context = context; }
AllocationContext_t gc_cause_context() { return _gc_cause_context; }
};
//
class G1ContextCauseSetter : public StackObj {
private:
G1CollectedHeap* _g1h;
public:
G1ContextCauseSetter(G1CollectedHeap* g1h, AllocationContext_t context)
: _g1h(g1h) {
if (TenantHeapIsolation) {
G1CollectedHeap::heap()->set_gc_cause_context(context);
}
}
~G1ContextCauseSetter() {
if (TenantHeapIsolation) {
G1CollectedHeap::heap()->set_gc_cause_context(AllocationContext::system());
}
}
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_HPP
......@@ -44,6 +44,7 @@ VM_G1CollectForAllocation::VM_G1CollectForAllocation(uint gc_count_before,
void VM_G1CollectForAllocation::doit() {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
GCCauseSetter x(g1h, _gc_cause);
G1ContextCauseSetter set_ctxt(g1h, this->allocation_context());
_result = g1h->satisfy_failed_allocation(_word_size, allocation_context(), &_pause_succeeded);
assert(_result == NULL || _pause_succeeded,
......@@ -53,6 +54,7 @@ void VM_G1CollectForAllocation::doit() {
void VM_G1CollectFull::doit() {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
GCCauseSetter x(g1h, _gc_cause);
G1ContextCauseSetter set_ctxt(g1h, this->allocation_context());
g1h->do_full_collection(false /* clear_all_soft_refs */);
}
......@@ -108,6 +110,7 @@ void VM_G1IncCollectionPause::doit() {
}
GCCauseSetter x(g1h, _gc_cause);
G1ContextCauseSetter set_ctxt(g1h, this->allocation_context());
if (_should_initiate_conc_mark) {
// It's safer to read old_marking_cycles_completed() here, given
// that noone else will be updating it concurrently. Since we'll
......
......@@ -53,6 +53,8 @@ public:
};
class VM_G1CollectFull: public VM_GC_Operation {
private:
AllocationContext_t _allocation_context;
public:
VM_G1CollectFull(uint gc_count_before,
uint full_gc_count_before,
......@@ -63,6 +65,8 @@ public:
virtual const char* name() const {
return "full garbage-first collection";
}
void set_allocation_context(AllocationContext_t context) { _allocation_context = context; }
AllocationContext_t allocation_context() { return _allocation_context; }
};
class VM_G1CollectForAllocation: public VM_G1OperationWithAllocRequest {
......
/*
* Copyright (c) 2020 Alibaba Group Holding Limited. 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. Alibaba designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*
*/
/*
* @test
* @requires os.family == "Linux"
* @requires os.arch == "amd64"
* @summary Test GC cause in GC log for tenant container
* @library /testlibrary
* @build TestTenantGCCause
* @run main/othervm/timeout=120 TestTenantGCCause
*/
import com.alibaba.tenant.TenantConfiguration;
import com.alibaba.tenant.TenantContainer;
import com.alibaba.tenant.TenantException;
import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.ProcessTools;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.oracle.java.testlibrary.Asserts.*;
public class TestTenantGCCause {
private static final int K = 1024;
// used by child process to create a new TenantContainer with given heap limit,
// and do allocation of given amount of bytes inside the TenantContainer;
static class AllocWorker {
// limit of TenantContainer, parsed from args[0];
private static long tenantLimit;
// total amount of bytes to be allocated, parsed from args[1];
private static long bytesToAlloc;
public static void main(String[] args) {
parseArgs(args);
TenantConfiguration config = new TenantConfiguration();
config.limitHeap(tenantLimit);
TenantContainer tenant = TenantContainer.create(config);
try {
tenant.run(()->{
List<byte[]> refs = new LinkedList<>(); // keep objects alive
long totalAllocated = 0;
while (totalAllocated < bytesToAlloc) {
byte[] obj = new byte[4 * K];
refs.add(obj);
totalAllocated += (obj.length + 16);
}
});
} catch (TenantException e) {
e.printStackTrace();
fail();
}
}
// parse size, can be '1234', '1K', '4M'
private static void parseArgs(String[] args) {
assertEquals(args.length, 2);
tenantLimit = parseSize(args[0]);
assertGreaterThan(tenantLimit, 0L);
bytesToAlloc = parseSize(args[1]);
}
private static final Pattern UNIT_PATTERN = Pattern.compile("(\\d+)([MmKkGg]{0,1})");
private static long parseSize(String s) {
Matcher m = UNIT_PATTERN.matcher(s);
long size = 0;
if (m.matches()) {
size = Long.parseLong(m.group(1));
if (m.groupCount() == 2) {
switch (m.group(2).toLowerCase()) {
case "k":
return (size * K);
case "m":
return (size * K * K);
case "g":
return (size * K * K * K);
default:
fail();
}
}
}
throw new IllegalArgumentException("Bad size format: " + s);
}
}
private void testYoungGCCause() {
try {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+MultiTenant",
"-XX:+TenantHeapThrottling",
"-XX:+UseG1GC",
"-Xmx1g",
"-Xms1g",
"-XX:G1HeapRegionSize=2m",
"-XX:+PrintGCDetails",
AllocWorker.class.getName(),
"4m",
"8m");
OutputAnalyzer out = new OutputAnalyzer(pb.start());
assertTrue(out.asLines().stream()
.sequential()
.peek(System.out::println)
.filter(l -> l.contains("[GC pause"))
.anyMatch(l -> l.contains("(tenant-0)")));
assertNotEquals(out.getExitValue(), 0);
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
private void testFullGCCause() {
try {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+MultiTenant",
"-XX:+TenantHeapThrottling",
"-XX:+UseG1GC",
"-Xmx1g",
"-Xms1g",
"-XX:G1HeapRegionSize=2m",
"-XX:+PrintGCDetails",
AllocWorker.class.getName(),
"4m",
"8m");
OutputAnalyzer out = new OutputAnalyzer(pb.start());
assertTrue(out.asLines().stream()
.sequential()
.peek(System.out::println)
.filter(l -> l.contains("[Full GC"))
.anyMatch(l -> l.contains("(tenant-0)")));
assertNotEquals(out.getExitValue(), 0);
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
public static void main(String[] args) {
TestTenantGCCause test = new TestTenantGCCause();
test.testYoungGCCause();
test.testFullGCCause();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册