提交 b6b17b79 编写于 作者: B brutisso

8027962: Per-phase timing measurements for strong roots processing

Reviewed-by: tschatzl, ecaspole
上级 0ccb7838
...@@ -249,7 +249,24 @@ G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : ...@@ -249,7 +249,24 @@ G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) :
_gc_par_phases[GCWorkerStart] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Start (ms)", false, G1Log::LevelFiner, 2); _gc_par_phases[GCWorkerStart] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Start (ms)", false, G1Log::LevelFiner, 2);
_gc_par_phases[ExtRootScan] = new WorkerDataArray<double>(max_gc_threads, "Ext Root Scanning (ms)", true, G1Log::LevelFiner, 2); _gc_par_phases[ExtRootScan] = new WorkerDataArray<double>(max_gc_threads, "Ext Root Scanning (ms)", true, G1Log::LevelFiner, 2);
_gc_par_phases[SATBFiltering] = new WorkerDataArray<double>(max_gc_threads, "SATB Filtering (ms)", true, G1Log::LevelFiner, 2);
// Root scanning phases
_gc_par_phases[ThreadRoots] = new WorkerDataArray<double>(max_gc_threads, "Thread Roots (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[StringTableRoots] = new WorkerDataArray<double>(max_gc_threads, "StringTable Roots (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[UniverseRoots] = new WorkerDataArray<double>(max_gc_threads, "Universe Roots (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[JNIRoots] = new WorkerDataArray<double>(max_gc_threads, "JNI Handles Roots (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray<double>(max_gc_threads, "ObjectSynchronizer Roots (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[FlatProfilerRoots] = new WorkerDataArray<double>(max_gc_threads, "FlatProfiler Roots (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[ManagementRoots] = new WorkerDataArray<double>(max_gc_threads, "Management Roots (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray<double>(max_gc_threads, "SystemDictionary Roots (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[CLDGRoots] = new WorkerDataArray<double>(max_gc_threads, "CLDG Roots (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[JVMTIRoots] = new WorkerDataArray<double>(max_gc_threads, "JVMTI Roots (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[CodeCacheRoots] = new WorkerDataArray<double>(max_gc_threads, "CodeCache Roots (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[CMRefRoots] = new WorkerDataArray<double>(max_gc_threads, "CM RefProcessor Roots (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[WaitForStrongCLD] = new WorkerDataArray<double>(max_gc_threads, "Wait For Strong CLD (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[WeakCLDRoots] = new WorkerDataArray<double>(max_gc_threads, "Weak CLD Roots (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[SATBFiltering] = new WorkerDataArray<double>(max_gc_threads, "SATB Filtering (ms)", true, G1Log::LevelFinest, 3);
_gc_par_phases[UpdateRS] = new WorkerDataArray<double>(max_gc_threads, "Update RS (ms)", true, G1Log::LevelFiner, 2); _gc_par_phases[UpdateRS] = new WorkerDataArray<double>(max_gc_threads, "Update RS (ms)", true, G1Log::LevelFiner, 2);
_gc_par_phases[ScanRS] = new WorkerDataArray<double>(max_gc_threads, "Scan RS (ms)", true, G1Log::LevelFiner, 2); _gc_par_phases[ScanRS] = new WorkerDataArray<double>(max_gc_threads, "Scan RS (ms)", true, G1Log::LevelFiner, 2);
_gc_par_phases[CodeRoots] = new WorkerDataArray<double>(max_gc_threads, "Code Root Scanning (ms)", true, G1Log::LevelFiner, 2); _gc_par_phases[CodeRoots] = new WorkerDataArray<double>(max_gc_threads, "Code Root Scanning (ms)", true, G1Log::LevelFiner, 2);
...@@ -282,8 +299,6 @@ void G1GCPhaseTimes::note_gc_start(uint active_gc_threads, bool mark_in_progress ...@@ -282,8 +299,6 @@ void G1GCPhaseTimes::note_gc_start(uint active_gc_threads, bool mark_in_progress
_gc_par_phases[i]->reset(); _gc_par_phases[i]->reset();
} }
_gc_par_phases[SATBFiltering]->set_enabled(mark_in_progress);
_gc_par_phases[StringDedupQueueFixup]->set_enabled(G1StringDedup::is_enabled()); _gc_par_phases[StringDedupQueueFixup]->set_enabled(G1StringDedup::is_enabled());
_gc_par_phases[StringDedupTableFixup]->set_enabled(G1StringDedup::is_enabled()); _gc_par_phases[StringDedupTableFixup]->set_enabled(G1StringDedup::is_enabled());
} }
......
...@@ -41,6 +41,20 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> { ...@@ -41,6 +41,20 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
enum GCParPhases { enum GCParPhases {
GCWorkerStart, GCWorkerStart,
ExtRootScan, ExtRootScan,
ThreadRoots,
StringTableRoots,
UniverseRoots,
JNIRoots,
ObjectSynchronizerRoots,
FlatProfilerRoots,
ManagementRoots,
SystemDictionaryRoots,
CLDGRoots,
JVMTIRoots,
CodeCacheRoots,
CMRefRoots,
WaitForStrongCLD,
WeakCLDRoots,
SATBFiltering, SATBFiltering,
UpdateRS, UpdateRS,
ScanRS, ScanRS,
......
...@@ -128,6 +128,7 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots, ...@@ -128,6 +128,7 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots,
uint worker_i) { uint worker_i) {
// First scan the shared roots. // First scan the shared roots.
double ext_roots_start = os::elapsedTime(); double ext_roots_start = os::elapsedTime();
G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots); BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots);
BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots); BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots);
...@@ -142,7 +143,9 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots, ...@@ -142,7 +143,9 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots,
trace_metadata ? scan_strong_clds : NULL, trace_metadata ? scan_strong_clds : NULL,
scan_strong_clds, scan_strong_clds,
trace_metadata ? NULL : scan_weak_clds, trace_metadata ? NULL : scan_weak_clds,
&root_code_blobs); &root_code_blobs,
phase_times,
worker_i);
// This is the point where this worker thread will not find more strong CLDs/nmethods. // This is the point where this worker thread will not find more strong CLDs/nmethods.
// Report this so G1 can synchronize the strong and weak CLDs/nmethods processing. // Report this so G1 can synchronize the strong and weak CLDs/nmethods processing.
...@@ -150,9 +153,11 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots, ...@@ -150,9 +153,11 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots,
worker_has_discovered_all_strong_classes(); worker_has_discovered_all_strong_classes();
} }
process_vm_roots(strong_roots, weak_roots); process_vm_roots(strong_roots, weak_roots, phase_times, worker_i);
{
// Now the CM ref_processor roots. // Now the CM ref_processor roots.
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CMRefRoots, worker_i);
if (!_process_strong_tasks->is_task_claimed(G1RP_PS_refProcessor_oops_do)) { if (!_process_strong_tasks->is_task_claimed(G1RP_PS_refProcessor_oops_do)) {
// We need to treat the discovered reference lists of the // We need to treat the discovered reference lists of the
// concurrent mark ref processor as roots and keep entries // concurrent mark ref processor as roots and keep entries
...@@ -160,14 +165,22 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots, ...@@ -160,14 +165,22 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots,
// until they can be processed at the end of marking. // until they can be processed at the end of marking.
_g1h->ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots); _g1h->ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots);
} }
}
if (trace_metadata) { if (trace_metadata) {
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WaitForStrongCLD, worker_i);
// Barrier to make sure all workers passed // Barrier to make sure all workers passed
// the strong CLD and strong nmethods phases. // the strong CLD and strong nmethods phases.
wait_until_all_strong_classes_discovered(); wait_until_all_strong_classes_discovered();
}
// Now take the complement of the strong CLDs. // Now take the complement of the strong CLDs.
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::WeakCLDRoots, worker_i);
ClassLoaderDataGraph::roots_cld_do(NULL, scan_weak_clds); ClassLoaderDataGraph::roots_cld_do(NULL, scan_weak_clds);
} else {
phase_times->record_time_secs(G1GCPhaseTimes::WaitForStrongCLD, worker_i, 0.0);
phase_times->record_time_secs(G1GCPhaseTimes::WeakCLDRoots, worker_i, 0.0);
} }
// Finish up any enqueued closure apps (attributed as object copy time). // Finish up any enqueued closure apps (attributed as object copy time).
...@@ -177,7 +190,6 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots, ...@@ -177,7 +190,6 @@ void G1RootProcessor::evacuate_roots(OopClosure* scan_non_heap_roots,
double obj_copy_time_sec = buf_scan_non_heap_roots.closure_app_seconds() double obj_copy_time_sec = buf_scan_non_heap_roots.closure_app_seconds()
+ buf_scan_non_heap_weak_roots.closure_app_seconds(); + buf_scan_non_heap_weak_roots.closure_app_seconds();
G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
phase_times->record_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, obj_copy_time_sec); phase_times->record_time_secs(G1GCPhaseTimes::ObjCopy, worker_i, obj_copy_time_sec);
double ext_root_time_sec = os::elapsedTime() - ext_roots_start - obj_copy_time_sec; double ext_root_time_sec = os::elapsedTime() - ext_roots_start - obj_copy_time_sec;
...@@ -201,8 +213,8 @@ void G1RootProcessor::process_strong_roots(OopClosure* oops, ...@@ -201,8 +213,8 @@ void G1RootProcessor::process_strong_roots(OopClosure* oops,
CLDClosure* clds, CLDClosure* clds,
CodeBlobClosure* blobs) { CodeBlobClosure* blobs) {
process_java_roots(oops, clds, clds, NULL, blobs); process_java_roots(oops, clds, clds, NULL, blobs, NULL, 0);
process_vm_roots(oops, NULL); process_vm_roots(oops, NULL, NULL, 0);
_process_strong_tasks->all_tasks_completed(); _process_strong_tasks->all_tasks_completed();
} }
...@@ -211,8 +223,8 @@ void G1RootProcessor::process_all_roots(OopClosure* oops, ...@@ -211,8 +223,8 @@ void G1RootProcessor::process_all_roots(OopClosure* oops,
CLDClosure* clds, CLDClosure* clds,
CodeBlobClosure* blobs) { CodeBlobClosure* blobs) {
process_java_roots(oops, NULL, clds, clds, NULL); process_java_roots(oops, NULL, clds, clds, NULL, NULL, 0);
process_vm_roots(oops, oops); process_vm_roots(oops, oops, NULL, 0);
if (!_process_strong_tasks->is_task_claimed(G1RP_PS_CodeCache_oops_do)) { if (!_process_strong_tasks->is_task_claimed(G1RP_PS_CodeCache_oops_do)) {
CodeCache::blobs_do(blobs); CodeCache::blobs_do(blobs);
...@@ -225,60 +237,95 @@ void G1RootProcessor::process_java_roots(OopClosure* strong_roots, ...@@ -225,60 +237,95 @@ void G1RootProcessor::process_java_roots(OopClosure* strong_roots,
CLDClosure* thread_stack_clds, CLDClosure* thread_stack_clds,
CLDClosure* strong_clds, CLDClosure* strong_clds,
CLDClosure* weak_clds, CLDClosure* weak_clds,
CodeBlobClosure* strong_code) { CodeBlobClosure* strong_code,
G1GCPhaseTimes* phase_times,
uint worker_i) {
assert(thread_stack_clds == NULL || weak_clds == NULL, "There is overlap between those, only one may be set"); assert(thread_stack_clds == NULL || weak_clds == NULL, "There is overlap between those, only one may be set");
// Iterating over the CLDG and the Threads are done early to allow us to // Iterating over the CLDG and the Threads are done early to allow us to
// first process the strong CLDs and nmethods and then, after a barrier, // first process the strong CLDs and nmethods and then, after a barrier,
// let the thread process the weak CLDs and nmethods. // let the thread process the weak CLDs and nmethods.
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CLDGRoots, worker_i);
if (!_process_strong_tasks->is_task_claimed(G1RP_PS_ClassLoaderDataGraph_oops_do)) { if (!_process_strong_tasks->is_task_claimed(G1RP_PS_ClassLoaderDataGraph_oops_do)) {
ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds); ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds);
} }
}
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ThreadRoots, worker_i);
Threads::possibly_parallel_oops_do(strong_roots, thread_stack_clds, strong_code); Threads::possibly_parallel_oops_do(strong_roots, thread_stack_clds, strong_code);
}
} }
void G1RootProcessor::process_vm_roots(OopClosure* strong_roots, void G1RootProcessor::process_vm_roots(OopClosure* strong_roots,
OopClosure* weak_roots) { OopClosure* weak_roots,
G1GCPhaseTimes* phase_times,
uint worker_i) {
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::UniverseRoots, worker_i);
if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Universe_oops_do)) { if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Universe_oops_do)) {
Universe::oops_do(strong_roots); Universe::oops_do(strong_roots);
} }
}
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::JNIRoots, worker_i);
if (!_process_strong_tasks->is_task_claimed(G1RP_PS_JNIHandles_oops_do)) { if (!_process_strong_tasks->is_task_claimed(G1RP_PS_JNIHandles_oops_do)) {
JNIHandles::oops_do(strong_roots); JNIHandles::oops_do(strong_roots);
} }
}
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ObjectSynchronizerRoots, worker_i);
if (!_process_strong_tasks-> is_task_claimed(G1RP_PS_ObjectSynchronizer_oops_do)) { if (!_process_strong_tasks-> is_task_claimed(G1RP_PS_ObjectSynchronizer_oops_do)) {
ObjectSynchronizer::oops_do(strong_roots); ObjectSynchronizer::oops_do(strong_roots);
} }
}
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::FlatProfilerRoots, worker_i);
if (!_process_strong_tasks->is_task_claimed(G1RP_PS_FlatProfiler_oops_do)) { if (!_process_strong_tasks->is_task_claimed(G1RP_PS_FlatProfiler_oops_do)) {
FlatProfiler::oops_do(strong_roots); FlatProfiler::oops_do(strong_roots);
} }
}
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ManagementRoots, worker_i);
if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Management_oops_do)) { if (!_process_strong_tasks->is_task_claimed(G1RP_PS_Management_oops_do)) {
Management::oops_do(strong_roots); Management::oops_do(strong_roots);
} }
}
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::JVMTIRoots, worker_i);
if (!_process_strong_tasks->is_task_claimed(G1RP_PS_jvmti_oops_do)) { if (!_process_strong_tasks->is_task_claimed(G1RP_PS_jvmti_oops_do)) {
JvmtiExport::oops_do(strong_roots); JvmtiExport::oops_do(strong_roots);
} }
}
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SystemDictionaryRoots, worker_i);
if (!_process_strong_tasks->is_task_claimed(G1RP_PS_SystemDictionary_oops_do)) { if (!_process_strong_tasks->is_task_claimed(G1RP_PS_SystemDictionary_oops_do)) {
SystemDictionary::roots_oops_do(strong_roots, weak_roots); SystemDictionary::roots_oops_do(strong_roots, weak_roots);
} }
}
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::StringTableRoots, worker_i);
// All threads execute the following. A specific chunk of buckets // All threads execute the following. A specific chunk of buckets
// from the StringTable are the individual tasks. // from the StringTable are the individual tasks.
if (weak_roots != NULL) { if (weak_roots != NULL) {
StringTable::possibly_parallel_oops_do(weak_roots); StringTable::possibly_parallel_oops_do(weak_roots);
} }
}
} }
void G1RootProcessor::scan_remembered_sets(G1ParPushHeapRSClosure* scan_rs, void G1RootProcessor::scan_remembered_sets(G1ParPushHeapRSClosure* scan_rs,
OopClosure* scan_non_heap_weak_roots, OopClosure* scan_non_heap_weak_roots,
uint worker_i) { uint worker_i) {
G1GCPhaseTimes* phase_times = _g1h->g1_policy()->phase_times();
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::CodeCacheRoots, worker_i);
// Now scan the complement of the collection set. // Now scan the complement of the collection set.
G1CodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots); G1CodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots);
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
class CLDClosure; class CLDClosure;
class CodeBlobClosure; class CodeBlobClosure;
class G1CollectedHeap; class G1CollectedHeap;
class G1GCPhaseTimes;
class G1ParPushHeapRSClosure; class G1ParPushHeapRSClosure;
class Monitor; class Monitor;
class OopClosure; class OopClosure;
...@@ -74,10 +75,14 @@ class G1RootProcessor : public StackObj { ...@@ -74,10 +75,14 @@ class G1RootProcessor : public StackObj {
CLDClosure* thread_stack_clds, CLDClosure* thread_stack_clds,
CLDClosure* scan_strong_clds, CLDClosure* scan_strong_clds,
CLDClosure* scan_weak_clds, CLDClosure* scan_weak_clds,
CodeBlobClosure* scan_strong_code); CodeBlobClosure* scan_strong_code,
G1GCPhaseTimes* phase_times,
uint worker_i);
void process_vm_roots(OopClosure* scan_non_heap_roots, void process_vm_roots(OopClosure* scan_non_heap_roots,
OopClosure* scan_non_heap_weak_roots); OopClosure* scan_non_heap_weak_roots,
G1GCPhaseTimes* phase_times,
uint worker_i);
public: public:
G1RootProcessor(G1CollectedHeap* g1h); G1RootProcessor(G1CollectedHeap* g1h);
......
/* /*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test TestGCLogMessages * @test TestGCLogMessages
* @bug 8035406 8027295 8035398 8019342 8027959 * @bug 8035406 8027295 8035398 8019342 8027959 8027962
* @summary Ensure that the PrintGCDetails output for a minor GC with G1 * @summary Ensure that the PrintGCDetails output for a minor GC with G1
* includes the expected necessary messages. * includes the expected necessary messages.
* @key gc * @key gc
...@@ -34,27 +34,78 @@ import com.oracle.java.testlibrary.ProcessTools; ...@@ -34,27 +34,78 @@ import com.oracle.java.testlibrary.ProcessTools;
import com.oracle.java.testlibrary.OutputAnalyzer; import com.oracle.java.testlibrary.OutputAnalyzer;
public class TestGCLogMessages { public class TestGCLogMessages {
private enum Level {
OFF, FINER, FINEST;
public boolean lessOrEqualTo(Level other) {
return this.compareTo(other) < 0;
}
}
private class LogMessageWithLevel {
String message;
Level level;
public LogMessageWithLevel(String message, Level level) {
this.message = message;
this.level = level;
}
};
private LogMessageWithLevel allLogMessages[] = new LogMessageWithLevel[] {
// Ext Root Scan
new LogMessageWithLevel("Thread Roots (ms)", Level.FINEST),
new LogMessageWithLevel("StringTable Roots (ms)", Level.FINEST),
new LogMessageWithLevel("Universe Roots (ms)", Level.FINEST),
new LogMessageWithLevel("JNI Handles Roots (ms)", Level.FINEST),
new LogMessageWithLevel("ObjectSynchronizer Roots (ms)", Level.FINEST),
new LogMessageWithLevel("FlatProfiler Roots", Level.FINEST),
new LogMessageWithLevel("Management Roots", Level.FINEST),
new LogMessageWithLevel("SystemDictionary Roots", Level.FINEST),
new LogMessageWithLevel("CLDG Roots", Level.FINEST),
new LogMessageWithLevel("JVMTI Roots", Level.FINEST),
new LogMessageWithLevel("CodeCache Roots", Level.FINEST),
new LogMessageWithLevel("SATB Filtering", Level.FINEST),
new LogMessageWithLevel("CM RefProcessor Roots", Level.FINEST),
new LogMessageWithLevel("Wait For Strong CLD", Level.FINEST),
new LogMessageWithLevel("Weak CLD Roots", Level.FINEST),
// Redirty Cards
new LogMessageWithLevel("Redirty Cards", Level.FINER),
new LogMessageWithLevel("Parallel Redirty", Level.FINEST),
new LogMessageWithLevel("Redirtied Cards", Level.FINEST),
// Misc Top-level
new LogMessageWithLevel("Code Root Purge", Level.FINER),
new LogMessageWithLevel("String Dedup Fixup", Level.FINER),
// Free CSet
new LogMessageWithLevel("Young Free CSet", Level.FINEST),
new LogMessageWithLevel("Non-Young Free CSet", Level.FINEST),
// Humongous Eager Reclaim
new LogMessageWithLevel("Humongous Reclaim", Level.FINER),
};
void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception {
for (LogMessageWithLevel l : messages) {
if (level.lessOrEqualTo(l.level)) {
output.shouldNotContain(l.message);
} else {
output.shouldContain(l.message);
}
}
}
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
testNormalLogs(); new TestGCLogMessages().testNormalLogs();
testWithToSpaceExhaustionLogs(); new TestGCLogMessages().testWithToSpaceExhaustionLogs();
} }
private static void testNormalLogs() throws Exception { private void testNormalLogs() throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
"-Xmx10M", "-Xmx10M",
GCTest.class.getName()); GCTest.class.getName());
OutputAnalyzer output = new OutputAnalyzer(pb.start()); OutputAnalyzer output = new OutputAnalyzer(pb.start());
checkMessagesAtLevel(output, allLogMessages, Level.OFF);
output.shouldNotContain("[Redirty Cards");
output.shouldNotContain("[Parallel Redirty");
output.shouldNotContain("[Redirtied Cards");
output.shouldNotContain("[Code Root Purge");
output.shouldNotContain("[String Dedup Fixup");
output.shouldNotContain("[Young Free CSet");
output.shouldNotContain("[Non-Young Free CSet");
output.shouldNotContain("[Humongous Reclaim");
output.shouldHaveExitValue(0); output.shouldHaveExitValue(0);
pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
...@@ -64,19 +115,7 @@ public class TestGCLogMessages { ...@@ -64,19 +115,7 @@ public class TestGCLogMessages {
GCTest.class.getName()); GCTest.class.getName());
output = new OutputAnalyzer(pb.start()); output = new OutputAnalyzer(pb.start());
checkMessagesAtLevel(output, allLogMessages, Level.FINER);
output.shouldContain("[Redirty Cards");
output.shouldNotContain("[Parallel Redirty");
output.shouldNotContain("[Redirtied Cards");
output.shouldContain("[Code Root Purge");
output.shouldContain("[String Dedup Fixup");
output.shouldNotContain("[Young Free CSet");
output.shouldNotContain("[Non-Young Free CSet");
output.shouldContain("[Humongous Reclaim");
output.shouldNotContain("[Humongous Total");
output.shouldNotContain("[Humongous Candidate");
output.shouldNotContain("[Humongous Reclaimed");
output.shouldHaveExitValue(0);
pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
"-XX:+UseStringDeduplication", "-XX:+UseStringDeduplication",
...@@ -87,48 +126,38 @@ public class TestGCLogMessages { ...@@ -87,48 +126,38 @@ public class TestGCLogMessages {
GCTest.class.getName()); GCTest.class.getName());
output = new OutputAnalyzer(pb.start()); output = new OutputAnalyzer(pb.start());
checkMessagesAtLevel(output, allLogMessages, Level.FINEST);
output.shouldContain("[Redirty Cards");
output.shouldContain("[Parallel Redirty");
output.shouldContain("[Redirtied Cards");
output.shouldContain("[Code Root Purge");
output.shouldContain("[String Dedup Fixup");
output.shouldContain("[Young Free CSet");
output.shouldContain("[Non-Young Free CSet");
output.shouldContain("[Humongous Reclaim");
output.shouldContain("[Humongous Total");
output.shouldContain("[Humongous Candidate");
output.shouldContain("[Humongous Reclaimed");
output.shouldHaveExitValue(0); output.shouldHaveExitValue(0);
} }
private static void testWithToSpaceExhaustionLogs() throws Exception { LogMessageWithLevel exhFailureMessages[] = new LogMessageWithLevel[] {
new LogMessageWithLevel("Evacuation Failure", Level.FINER),
new LogMessageWithLevel("Recalculate Used", Level.FINEST),
new LogMessageWithLevel("Remove Self Forwards", Level.FINEST),
new LogMessageWithLevel("Restore RemSet", Level.FINEST),
};
private void testWithToSpaceExhaustionLogs() throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
"-Xmx10M", "-Xmx32M",
"-Xmn5M", "-Xmn16M",
"-XX:+PrintGCDetails", "-XX:+PrintGCDetails",
GCTestWithToSpaceExhaustion.class.getName()); GCTestWithToSpaceExhaustion.class.getName());
OutputAnalyzer output = new OutputAnalyzer(pb.start()); OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("[Evacuation Failure"); checkMessagesAtLevel(output, exhFailureMessages, Level.FINER);
output.shouldNotContain("[Recalculate Used");
output.shouldNotContain("[Remove Self Forwards");
output.shouldNotContain("[Restore RemSet");
output.shouldHaveExitValue(0); output.shouldHaveExitValue(0);
pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
"-Xmx10M", "-Xmx32M",
"-Xmn5M", "-Xmn16M",
"-XX:+PrintGCDetails", "-XX:+PrintGCDetails",
"-XX:+UnlockExperimentalVMOptions", "-XX:+UnlockExperimentalVMOptions",
"-XX:G1LogLevel=finest", "-XX:G1LogLevel=finest",
GCTestWithToSpaceExhaustion.class.getName()); GCTestWithToSpaceExhaustion.class.getName());
output = new OutputAnalyzer(pb.start()); output = new OutputAnalyzer(pb.start());
output.shouldContain("[Evacuation Failure"); checkMessagesAtLevel(output, exhFailureMessages, Level.FINEST);
output.shouldContain("[Recalculate Used");
output.shouldContain("[Remove Self Forwards");
output.shouldContain("[Restore RemSet");
output.shouldHaveExitValue(0); output.shouldHaveExitValue(0);
} }
...@@ -148,7 +177,7 @@ public class TestGCLogMessages { ...@@ -148,7 +177,7 @@ public class TestGCLogMessages {
private static byte[] garbage; private static byte[] garbage;
private static byte[] largeObject; private static byte[] largeObject;
public static void main(String [] args) { public static void main(String [] args) {
largeObject = new byte[5*1024*1024]; largeObject = new byte[16*1024*1024];
System.out.println("Creating garbage"); System.out.println("Creating garbage");
// create 128MB of garbage. This should result in at least one GC, // create 128MB of garbage. This should result in at least one GC,
// some of them with to-space exhaustion. // some of them with to-space exhaustion.
...@@ -159,3 +188,4 @@ public class TestGCLogMessages { ...@@ -159,3 +188,4 @@ public class TestGCLogMessages {
} }
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册