提交 fca499f2 编写于 作者: J jmasa

6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.

Summary: Ensure a full GC that clears SoftReferences before throwing an out-of-memory
Reviewed-by: ysr, jcoomes
上级 6e17b39b
/*
* Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2007-2010 Sun Microsystems, 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,11 +32,10 @@ class ConcurrentMarkSweepPolicy : public TwoGenerationCollectorPolicy {
ConcurrentMarkSweepPolicy* as_concurrent_mark_sweep_policy() { return this; }
void initialize_gc_policy_counters();
#if 1
virtual void initialize_size_policy(size_t init_eden_size,
size_t init_promo_size,
size_t init_survivor_size);
#endif
// Returns true if the incremental mode is enabled.
virtual bool has_soft_ended_eden();
......
/*
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2001-2010 Sun Microsystems, 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
......@@ -1815,8 +1815,19 @@ NOT_PRODUCT(
do_compaction_work(clear_all_soft_refs);
// Has the GC time limit been exceeded?
check_gc_time_limit();
DefNewGeneration* young_gen = _young_gen->as_DefNewGeneration();
size_t max_eden_size = young_gen->max_capacity() -
young_gen->to()->capacity() -
young_gen->from()->capacity();
GenCollectedHeap* gch = GenCollectedHeap::heap();
GCCause::Cause gc_cause = gch->gc_cause();
size_policy()->check_gc_overhead_limit(_young_gen->used(),
young_gen->eden()->used(),
_cmsGen->max_capacity(),
max_eden_size,
full,
gc_cause,
gch->collector_policy());
} else {
do_mark_sweep_work(clear_all_soft_refs, first_state,
should_start_over);
......@@ -1828,55 +1839,6 @@ NOT_PRODUCT(
return;
}
void CMSCollector::check_gc_time_limit() {
// Ignore explicit GC's. Exiting here does not set the flag and
// does not reset the count. Updating of the averages for system
// GC's is still controlled by UseAdaptiveSizePolicyWithSystemGC.
GCCause::Cause gc_cause = GenCollectedHeap::heap()->gc_cause();
if (GCCause::is_user_requested_gc(gc_cause) ||
GCCause::is_serviceability_requested_gc(gc_cause)) {
return;
}
// Calculate the fraction of the CMS generation was freed during
// the last collection.
// Only consider the STW compacting cost for now.
//
// Note that the gc time limit test only works for the collections
// of the young gen + tenured gen and not for collections of the
// permanent gen. That is because the calculation of the space
// freed by the collection is the free space in the young gen +
// tenured gen.
double fraction_free =
((double)_cmsGen->free())/((double)_cmsGen->max_capacity());
if ((100.0 * size_policy()->compacting_gc_cost()) >
((double) GCTimeLimit) &&
((fraction_free * 100) < GCHeapFreeLimit)) {
size_policy()->inc_gc_time_limit_count();
if (UseGCOverheadLimit &&
(size_policy()->gc_time_limit_count() >
AdaptiveSizePolicyGCTimeLimitThreshold)) {
size_policy()->set_gc_time_limit_exceeded(true);
// Avoid consecutive OOM due to the gc time limit by resetting
// the counter.
size_policy()->reset_gc_time_limit_count();
if (PrintGCDetails) {
gclog_or_tty->print_cr(" GC is exceeding overhead limit "
"of %d%%", GCTimeLimit);
}
} else {
if (PrintGCDetails) {
gclog_or_tty->print_cr(" GC would exceed overhead limit "
"of %d%%", GCTimeLimit);
}
}
} else {
size_policy()->reset_gc_time_limit_count();
}
}
// Resize the perm generation and the tenured generation
// after obtaining the free list locks for the
// two generations.
......@@ -6182,6 +6144,11 @@ void CMSCollector::reset(bool asynch) {
}
curAddr = chunk.end();
}
// A successful mostly concurrent collection has been done.
// Because only the full (i.e., concurrent mode failure) collections
// are being measured for gc overhead limits, clean the "near" flag
// and count.
sp->reset_gc_overhead_limit_count();
_collectorState = Idling;
} else {
// already have the lock
......
/*
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2001-2010 Sun Microsystems, 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
......@@ -570,10 +570,6 @@ class CMSCollector: public CHeapObj {
ConcurrentMarkSweepPolicy* _collector_policy;
ConcurrentMarkSweepPolicy* collector_policy() { return _collector_policy; }
// Check whether the gc time limit has been
// exceeded and set the size policy flag
// appropriately.
void check_gc_time_limit();
// XXX Move these to CMSStats ??? FIX ME !!!
elapsedTimer _inter_sweep_timer; // time between sweeps
elapsedTimer _intra_sweep_timer; // time _in_ sweeps
......
/*
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2001-2010 Sun Microsystems, 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
......@@ -920,13 +920,19 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs,
assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread");
const bool do_clear_all_soft_refs = clear_all_soft_refs ||
collector_policy()->should_clear_all_soft_refs();
ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy());
{
IsGCActiveMark x;
// Timing
gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
TraceTime t(full ? "Full GC (System.gc())" : "Full GC", PrintGC, true, gclog_or_tty);
TraceTime t(full ? "Full GC (System.gc())" : "Full GC",
PrintGC, true, gclog_or_tty);
TraceMemoryManagerStats tms(true /* fullGC */);
......@@ -985,12 +991,12 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs,
ReferenceProcessorIsAliveMutator rp_is_alive_null(ref_processor(), NULL);
ref_processor()->enable_discovery();
ref_processor()->setup_policy(clear_all_soft_refs);
ref_processor()->setup_policy(do_clear_all_soft_refs);
// Do collection work
{
HandleMark hm; // Discard invalid handles created during gc
G1MarkSweep::invoke_at_safepoint(ref_processor(), clear_all_soft_refs);
G1MarkSweep::invoke_at_safepoint(ref_processor(), do_clear_all_soft_refs);
}
// Because freeing humongous regions may have added some unclean
// regions, it is necessary to tear down again before rebuilding.
......@@ -1208,6 +1214,9 @@ G1CollectedHeap::satisfy_failed_allocation(size_t word_size) {
return result;
}
assert(!collector_policy()->should_clear_all_soft_refs(),
"Flag should have been handled and cleared prior to this point");
// What else? We might try synchronous finalization later. If the total
// space available is large enough for the allocation, then a more
// complete compaction phase than we've tried so far might be
......
/*
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2001-2010 Sun Microsystems, 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,6 +31,12 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
bool clear_all_softrefs) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
SharedHeap* sh = SharedHeap::heap();
#ifdef ASSERT
if (sh->collector_policy()->should_clear_all_soft_refs()) {
assert(clear_all_softrefs, "Policy should have been checked earler");
}
#endif
// hook up weak ref data so it can be used during Mark-Sweep
assert(GenMarkSweep::ref_processor() == NULL, "no stomping");
assert(rp != NULL, "should be non-NULL");
......@@ -44,7 +50,6 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
// Increment the invocation count for the permanent generation, since it is
// implicitly collected whenever we do a full mark sweep collection.
SharedHeap* sh = SharedHeap::heap();
sh->perm_gen()->stat_record()->invocations++;
bool marked_for_unloading = false;
......
//
// Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
// Copyright 2001-2010 Sun Microsystems, 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
......@@ -161,8 +161,10 @@ parMarkBitMap.cpp psParallelCompact.hpp
parMarkBitMap.hpp bitMap.inline.hpp
parMarkBitMap.hpp psVirtualspace.hpp
psAdaptiveSizePolicy.cpp collectorPolicy.hpp
psAdaptiveSizePolicy.cpp gcPolicyCounters.hpp
psAdaptiveSizePolicy.cpp gcCause.hpp
psAdaptiveSizePolicy.cpp generationSizer.hpp
psAdaptiveSizePolicy.cpp psAdaptiveSizePolicy.hpp
psAdaptiveSizePolicy.cpp psGCAdaptivePolicyCounters.hpp
psAdaptiveSizePolicy.cpp psScavenge.hpp
......@@ -215,6 +217,7 @@ psMarkSweep.cpp events.hpp
psMarkSweep.cpp fprofiler.hpp
psMarkSweep.cpp gcCause.hpp
psMarkSweep.cpp gcLocker.inline.hpp
psMarkSweep.cpp generationSizer.hpp
psMarkSweep.cpp isGCActiveMark.hpp
psMarkSweep.cpp oop.inline.hpp
psMarkSweep.cpp memoryService.hpp
......@@ -256,6 +259,7 @@ psParallelCompact.cpp fprofiler.hpp
psParallelCompact.cpp gcCause.hpp
psParallelCompact.cpp gcLocker.inline.hpp
psParallelCompact.cpp gcTaskManager.hpp
psParallelCompact.cpp generationSizer.hpp
psParallelCompact.cpp isGCActiveMark.hpp
psParallelCompact.cpp management.hpp
psParallelCompact.cpp memoryService.hpp
......@@ -344,10 +348,12 @@ psPromotionLAB.hpp objectStartArray.hpp
psScavenge.cpp psAdaptiveSizePolicy.hpp
psScavenge.cpp biasedLocking.hpp
psScavenge.cpp cardTableExtension.hpp
psScavenge.cpp collectorPolicy.hpp
psScavenge.cpp fprofiler.hpp
psScavenge.cpp gcCause.hpp
psScavenge.cpp gcLocker.inline.hpp
psScavenge.cpp gcTaskManager.hpp
psScavenge.cpp generationSizer.hpp
psScavenge.cpp handles.inline.hpp
psScavenge.cpp isGCActiveMark.hpp
psScavenge.cpp oop.inline.hpp
......
//
// Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
// Copyright 2007-2010 Sun Microsystems, 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
......@@ -29,6 +29,7 @@ adaptiveSizePolicy.hpp allocation.hpp
adaptiveSizePolicy.hpp universe.hpp
adaptiveSizePolicy.cpp adaptiveSizePolicy.hpp
adaptiveSizePolicy.cpp collectorPolicy.hpp
adaptiveSizePolicy.cpp gcCause.hpp
adaptiveSizePolicy.cpp ostream.hpp
adaptiveSizePolicy.cpp timer.hpp
......
/*
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2001-2010 Sun Microsystems, 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
......@@ -892,6 +892,10 @@ void ParNewGeneration::collect(bool full,
}
swap_spaces();
// A successful scavenge should restart the GC time limit count which is
// for full GC's.
size_policy->reset_gc_overhead_limit_count();
assert(to()->is_empty(), "to space should be empty now");
} else {
assert(HandlePromotionFailure,
......
/*
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2001-2010 Sun Microsystems, 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
......@@ -54,15 +54,16 @@ jint ParallelScavengeHeap::initialize() {
CollectedHeap::pre_initialize();
// Cannot be initialized until after the flags are parsed
GenerationSizer flag_parser;
// GenerationSizer flag_parser;
_collector_policy = new GenerationSizer();
size_t yg_min_size = flag_parser.min_young_gen_size();
size_t yg_max_size = flag_parser.max_young_gen_size();
size_t og_min_size = flag_parser.min_old_gen_size();
size_t og_max_size = flag_parser.max_old_gen_size();
size_t yg_min_size = _collector_policy->min_young_gen_size();
size_t yg_max_size = _collector_policy->max_young_gen_size();
size_t og_min_size = _collector_policy->min_old_gen_size();
size_t og_max_size = _collector_policy->max_old_gen_size();
// Why isn't there a min_perm_gen_size()?
size_t pg_min_size = flag_parser.perm_gen_size();
size_t pg_max_size = flag_parser.max_perm_gen_size();
size_t pg_min_size = _collector_policy->perm_gen_size();
size_t pg_max_size = _collector_policy->max_perm_gen_size();
trace_gen_sizes("ps heap raw",
pg_min_size, pg_max_size,
......@@ -89,12 +90,14 @@ jint ParallelScavengeHeap::initialize() {
// move to the common code.
yg_min_size = align_size_up(yg_min_size, yg_align);
yg_max_size = align_size_up(yg_max_size, yg_align);
size_t yg_cur_size = align_size_up(flag_parser.young_gen_size(), yg_align);
size_t yg_cur_size =
align_size_up(_collector_policy->young_gen_size(), yg_align);
yg_cur_size = MAX2(yg_cur_size, yg_min_size);
og_min_size = align_size_up(og_min_size, og_align);
og_max_size = align_size_up(og_max_size, og_align);
size_t og_cur_size = align_size_up(flag_parser.old_gen_size(), og_align);
size_t og_cur_size =
align_size_up(_collector_policy->old_gen_size(), og_align);
og_cur_size = MAX2(og_cur_size, og_min_size);
pg_min_size = align_size_up(pg_min_size, pg_align);
......@@ -355,6 +358,11 @@ HeapWord* ParallelScavengeHeap::mem_allocate(
assert(Thread::current() != (Thread*)VMThread::vm_thread(), "should not be in vm thread");
assert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock");
// In general gc_overhead_limit_was_exceeded should be false so
// set it so here and reset it to true only if the gc time
// limit is being exceeded as checked below.
*gc_overhead_limit_was_exceeded = false;
HeapWord* result = young_gen()->allocate(size, is_tlab);
uint loop_count = 0;
......@@ -428,24 +436,6 @@ HeapWord* ParallelScavengeHeap::mem_allocate(
if (result == NULL) {
// Exit the loop if if the gc time limit has been exceeded.
// The allocation must have failed above (result must be NULL),
// and the most recent collection must have exceeded the
// gc time limit. Exit the loop so that an out-of-memory
// will be thrown (returning a NULL will do that), but
// clear gc_time_limit_exceeded so that the next collection
// will succeeded if the applications decides to handle the
// out-of-memory and tries to go on.
*gc_overhead_limit_was_exceeded = size_policy()->gc_time_limit_exceeded();
if (size_policy()->gc_time_limit_exceeded()) {
size_policy()->set_gc_time_limit_exceeded(false);
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("ParallelScavengeHeap::mem_allocate: "
"return NULL because gc_time_limit_exceeded is set");
}
return NULL;
}
// Generate a VM operation
VM_ParallelGCFailedAllocation op(size, is_tlab, gc_count);
VMThread::execute(&op);
......@@ -463,16 +453,34 @@ HeapWord* ParallelScavengeHeap::mem_allocate(
assert(op.result() == NULL, "must be NULL if gc_locked() is true");
continue; // retry and/or stall as necessary
}
// If a NULL result is being returned, an out-of-memory
// will be thrown now. Clear the gc_time_limit_exceeded
// flag to avoid the following situation.
// gc_time_limit_exceeded is set during a collection
// the collection fails to return enough space and an OOM is thrown
// the next GC is skipped because the gc_time_limit_exceeded
// flag is set and another OOM is thrown
if (op.result() == NULL) {
size_policy()->set_gc_time_limit_exceeded(false);
// Exit the loop if the gc time limit has been exceeded.
// The allocation must have failed above ("result" guarding
// this path is NULL) and the most recent collection has exceeded the
// gc overhead limit (although enough may have been collected to
// satisfy the allocation). Exit the loop so that an out-of-memory
// will be thrown (return a NULL ignoring the contents of
// op.result()),
// but clear gc_overhead_limit_exceeded so that the next collection
// starts with a clean slate (i.e., forgets about previous overhead
// excesses). Fill op.result() with a filler object so that the
// heap remains parsable.
const bool limit_exceeded = size_policy()->gc_overhead_limit_exceeded();
const bool softrefs_clear = collector_policy()->all_soft_refs_clear();
assert(!limit_exceeded || softrefs_clear, "Should have been cleared");
if (limit_exceeded && softrefs_clear) {
*gc_overhead_limit_was_exceeded = true;
size_policy()->set_gc_overhead_limit_exceeded(false);
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("ParallelScavengeHeap::mem_allocate: "
"return NULL because gc_overhead_limit_exceeded is set");
}
if (op.result() != NULL) {
CollectedHeap::fill_with_object(op.result(), size);
}
return NULL;
}
return op.result();
}
}
......@@ -613,14 +621,15 @@ HeapWord* ParallelScavengeHeap::permanent_mem_allocate(size_t size) {
// and the most recent collection must have exceeded the
// gc time limit. Exit the loop so that an out-of-memory
// will be thrown (returning a NULL will do that), but
// clear gc_time_limit_exceeded so that the next collection
// clear gc_overhead_limit_exceeded so that the next collection
// will succeeded if the applications decides to handle the
// out-of-memory and tries to go on.
if (size_policy()->gc_time_limit_exceeded()) {
size_policy()->set_gc_time_limit_exceeded(false);
const bool limit_exceeded = size_policy()->gc_overhead_limit_exceeded();
if (limit_exceeded) {
size_policy()->set_gc_overhead_limit_exceeded(false);
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("ParallelScavengeHeap::permanent_mem_allocate: "
"return NULL because gc_time_limit_exceeded is set");
gclog_or_tty->print_cr("ParallelScavengeHeap::permanent_mem_allocate:"
" return NULL because gc_overhead_limit_exceeded is set");
}
assert(result == NULL, "Allocation did not fail");
return NULL;
......@@ -643,14 +652,15 @@ HeapWord* ParallelScavengeHeap::permanent_mem_allocate(size_t size) {
continue; // retry and/or stall as necessary
}
// If a NULL results is being returned, an out-of-memory
// will be thrown now. Clear the gc_time_limit_exceeded
// will be thrown now. Clear the gc_overhead_limit_exceeded
// flag to avoid the following situation.
// gc_time_limit_exceeded is set during a collection
// gc_overhead_limit_exceeded is set during a collection
// the collection fails to return enough space and an OOM is thrown
// the next GC is skipped because the gc_time_limit_exceeded
// flag is set and another OOM is thrown
// a subsequent GC prematurely throws an out-of-memory because
// the gc_overhead_limit_exceeded counts did not start
// again from 0.
if (op.result() == NULL) {
size_policy()->set_gc_time_limit_exceeded(false);
size_policy()->reset_gc_overhead_limit_count();
}
return op.result();
}
......
/*
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2001-2010 Sun Microsystems, 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
......@@ -25,6 +25,8 @@
class AdjoiningGenerations;
class GCTaskManager;
class PSAdaptiveSizePolicy;
class GenerationSizer;
class CollectorPolicy;
class ParallelScavengeHeap : public CollectedHeap {
friend class VMStructs;
......@@ -43,6 +45,8 @@ class ParallelScavengeHeap : public CollectedHeap {
size_t _young_gen_alignment;
size_t _old_gen_alignment;
GenerationSizer* _collector_policy;
inline size_t set_alignment(size_t& var, size_t val);
// Collection of generations that are adjacent in the
......@@ -72,6 +76,9 @@ class ParallelScavengeHeap : public CollectedHeap {
return CollectedHeap::ParallelScavengeHeap;
}
CollectorPolicy* collector_policy() const { return (CollectorPolicy*) _collector_policy; }
// GenerationSizer* collector_policy() const { return _collector_policy; }
static PSYoungGen* young_gen() { return _young_gen; }
static PSOldGen* old_gen() { return _old_gen; }
static PSPermGen* perm_gen() { return _perm_gen; }
......
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2010 Sun Microsystems, 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
......@@ -184,18 +184,19 @@ void PSAdaptiveSizePolicy::clear_generation_free_space_flags() {
set_change_young_gen_for_maj_pauses(0);
}
// If this is not a full GC, only test and modify the young generation.
void PSAdaptiveSizePolicy::compute_generation_free_space(size_t young_live,
size_t eden_live,
size_t old_live,
size_t perm_live,
size_t cur_eden,
size_t max_old_gen_size,
size_t max_eden_size,
bool is_full_gc,
GCCause::Cause gc_cause) {
void PSAdaptiveSizePolicy::compute_generation_free_space(
size_t young_live,
size_t eden_live,
size_t old_live,
size_t perm_live,
size_t cur_eden,
size_t max_old_gen_size,
size_t max_eden_size,
bool is_full_gc,
GCCause::Cause gc_cause,
CollectorPolicy* collector_policy) {
// Update statistics
// Time statistics are updated as we go, update footprint stats here
......@@ -380,91 +381,16 @@ void PSAdaptiveSizePolicy::compute_generation_free_space(size_t young_live,
// Is too much time being spent in GC?
// Is the heap trying to grow beyond it's limits?
const size_t free_in_old_gen = (size_t)(max_old_gen_size - avg_old_live()->average());
const size_t free_in_old_gen =
(size_t)(max_old_gen_size - avg_old_live()->average());
if (desired_promo_size > free_in_old_gen && desired_eden_size > eden_limit) {
// eden_limit is the upper limit on the size of eden based on
// the maximum size of the young generation and the sizes
// of the survivor space.
// The question being asked is whether the gc costs are high
// and the space being recovered by a collection is low.
// free_in_young_gen is the free space in the young generation
// after a collection and promo_live is the free space in the old
// generation after a collection.
//
// Use the minimum of the current value of the live in the
// young gen or the average of the live in the young gen.
// If the current value drops quickly, that should be taken
// into account (i.e., don't trigger if the amount of free
// space has suddenly jumped up). If the current is much
// higher than the average, use the average since it represents
// the longer term behavor.
const size_t live_in_eden = MIN2(eden_live, (size_t) avg_eden_live()->average());
const size_t free_in_eden = eden_limit > live_in_eden ?
eden_limit - live_in_eden : 0;
const size_t total_free_limit = free_in_old_gen + free_in_eden;
const size_t total_mem = max_old_gen_size + max_eden_size;
const double mem_free_limit = total_mem * (GCHeapFreeLimit/100.0);
if (PrintAdaptiveSizePolicy && (Verbose ||
(total_free_limit < (size_t) mem_free_limit))) {
gclog_or_tty->print_cr(
"PSAdaptiveSizePolicy::compute_generation_free_space limits:"
" promo_limit: " SIZE_FORMAT
" eden_limit: " SIZE_FORMAT
" total_free_limit: " SIZE_FORMAT
" max_old_gen_size: " SIZE_FORMAT
" max_eden_size: " SIZE_FORMAT
" mem_free_limit: " SIZE_FORMAT,
promo_limit, eden_limit, total_free_limit,
max_old_gen_size, max_eden_size,
(size_t) mem_free_limit);
}
if (is_full_gc) {
if (gc_cost() > gc_cost_limit &&
total_free_limit < (size_t) mem_free_limit) {
// Collections, on average, are taking too much time, and
// gc_cost() > gc_cost_limit
// we have too little space available after a full gc.
// total_free_limit < mem_free_limit
// where
// total_free_limit is the free space available in
// both generations
// total_mem is the total space available for allocation
// in both generations (survivor spaces are not included
// just as they are not included in eden_limit).
// mem_free_limit is a fraction of total_mem judged to be an
// acceptable amount that is still unused.
// The heap can ask for the value of this variable when deciding
// whether to thrown an OutOfMemory error.
// Note that the gc time limit test only works for the collections
// of the young gen + tenured gen and not for collections of the
// permanent gen. That is because the calculation of the space
// freed by the collection is the free space in the young gen +
// tenured gen.
// Ignore explicit GC's. Ignoring explicit GC's at this level
// is the equivalent of the GC did not happen as far as the
// overhead calculation is concerted (i.e., the flag is not set
// and the count is not affected). Also the average will not
// have been updated unless UseAdaptiveSizePolicyWithSystemGC is on.
if (!GCCause::is_user_requested_gc(gc_cause) &&
!GCCause::is_serviceability_requested_gc(gc_cause)) {
inc_gc_time_limit_count();
if (UseGCOverheadLimit &&
(gc_time_limit_count() > AdaptiveSizePolicyGCTimeLimitThreshold)){
// All conditions have been met for throwing an out-of-memory
_gc_time_limit_exceeded = true;
// Avoid consecutive OOM due to the gc time limit by resetting
// the counter.
reset_gc_time_limit_count();
}
_print_gc_time_limit_would_be_exceeded = true;
}
} else {
// Did not exceed overhead limits
reset_gc_time_limit_count();
}
}
check_gc_overhead_limit(young_live,
eden_live,
max_old_gen_size,
max_eden_size,
is_full_gc,
gc_cause,
collector_policy);
}
......
/*
* Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2010 Sun Microsystems, 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
......@@ -45,6 +45,7 @@
// Forward decls
class elapsedTimer;
class GenerationSizer;
class PSAdaptiveSizePolicy : public AdaptiveSizePolicy {
friend class PSGCAdaptivePolicyCounters;
......@@ -340,7 +341,8 @@ class PSAdaptiveSizePolicy : public AdaptiveSizePolicy {
size_t max_old_gen_size,
size_t max_eden_size,
bool is_full_gc,
GCCause::Cause gc_cause);
GCCause::Cause gc_cause,
CollectorPolicy* collector_policy);
// Calculates new survivor space size; returns a new tenuring threshold
// value. Stores new survivor size in _survivor_size.
......
/*
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2010 Sun Microsystems, 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
......@@ -117,11 +117,13 @@ PSGCAdaptivePolicyCounters::PSGCAdaptivePolicyCounters(const char* name_arg,
PerfData::U_Bytes, (jlong) ps_size_policy()->avg_base_footprint()->average(), CHECK);
cname = PerfDataManager::counter_name(name_space(), "gcTimeLimitExceeded");
_gc_time_limit_exceeded = PerfDataManager::create_variable(SUN_GC, cname,
PerfData::U_Events, ps_size_policy()->gc_time_limit_exceeded(), CHECK);
_gc_overhead_limit_exceeded_counter =
PerfDataManager::create_variable(SUN_GC, cname,
PerfData::U_Events, ps_size_policy()->gc_overhead_limit_exceeded(), CHECK);
cname = PerfDataManager::counter_name(name_space(), "liveAtLastFullGc");
_live_at_last_full_gc = PerfDataManager::create_variable(SUN_GC, cname,
_live_at_last_full_gc_counter =
PerfDataManager::create_variable(SUN_GC, cname,
PerfData::U_Bytes, ps_size_policy()->live_at_last_full_gc(), CHECK);
cname = PerfDataManager::counter_name(name_space(), "majorPauseOldSlope");
......@@ -189,6 +191,8 @@ void PSGCAdaptivePolicyCounters::update_counters_from_policy() {
update_minor_pause_old_slope();
update_major_pause_young_slope();
update_minor_collection_slope_counter();
update_gc_overhead_limit_exceeded_counter();
update_live_at_last_full_gc_counter();
}
}
......
/*
* Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2003-2010 Sun Microsystems, 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
......@@ -44,8 +44,8 @@ class PSGCAdaptivePolicyCounters : public GCAdaptivePolicyCounters {
PerfVariable* _live_space;
PerfVariable* _free_space;
PerfVariable* _avg_base_footprint;
PerfVariable* _gc_time_limit_exceeded;
PerfVariable* _live_at_last_full_gc;
PerfVariable* _gc_overhead_limit_exceeded_counter;
PerfVariable* _live_at_last_full_gc_counter;
PerfVariable* _old_capacity;
PerfVariable* _boundary_moved;
......@@ -169,6 +169,14 @@ class PSGCAdaptivePolicyCounters : public GCAdaptivePolicyCounters {
(jlong)(ps_size_policy()->major_pause_young_slope() * 1000)
);
}
inline void update_gc_overhead_limit_exceeded_counter() {
_gc_overhead_limit_exceeded_counter->set_value(
(jlong) ps_size_policy()->gc_overhead_limit_exceeded());
}
inline void update_live_at_last_full_gc_counter() {
_live_at_last_full_gc_counter->set_value(
(jlong)(ps_size_policy()->live_at_last_full_gc()));
}
inline void update_scavenge_skipped(int cause) {
_scavenge_skipped->set_value(cause);
......
/*
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2001-2010 Sun Microsystems, 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
......@@ -46,6 +46,12 @@ void PSMarkSweep::initialize() {
//
// Note that this method should only be called from the vm_thread while
// at a safepoint!
//
// Note that the all_soft_refs_clear flag in the collector policy
// may be true because this method can be called without intervening
// activity. For example when the heap space is tight and full measure
// are being taken to free space.
void PSMarkSweep::invoke(bool maximum_heap_compaction) {
assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
assert(Thread::current() == (Thread*)VMThread::vm_thread(), "should be in vm thread");
......@@ -54,24 +60,18 @@ void PSMarkSweep::invoke(bool maximum_heap_compaction) {
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
GCCause::Cause gc_cause = heap->gc_cause();
PSAdaptiveSizePolicy* policy = heap->size_policy();
IsGCActiveMark mark;
// Before each allocation/collection attempt, find out from the
// policy object if GCs are, on the whole, taking too long. If so,
// bail out without attempting a collection. The exceptions are
// for explicitly requested GC's.
if (!policy->gc_time_limit_exceeded() ||
GCCause::is_user_requested_gc(gc_cause) ||
GCCause::is_serviceability_requested_gc(gc_cause)) {
IsGCActiveMark mark;
if (ScavengeBeforeFullGC) {
PSScavenge::invoke_no_policy();
}
int count = (maximum_heap_compaction)?1:MarkSweepAlwaysCompactCount;
IntFlagSetting flag_setting(MarkSweepAlwaysCompactCount, count);
PSMarkSweep::invoke_no_policy(maximum_heap_compaction);
if (ScavengeBeforeFullGC) {
PSScavenge::invoke_no_policy();
}
const bool clear_all_soft_refs =
heap->collector_policy()->should_clear_all_soft_refs();
int count = (maximum_heap_compaction)?1:MarkSweepAlwaysCompactCount;
IntFlagSetting flag_setting(MarkSweepAlwaysCompactCount, count);
PSMarkSweep::invoke_no_policy(clear_all_soft_refs || maximum_heap_compaction);
}
// This method contains no policy. You should probably
......@@ -89,6 +89,10 @@ void PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
PSAdaptiveSizePolicy* size_policy = heap->size_policy();
// The scope of casr should end after code that can change
// CollectorPolicy::_should_clear_all_soft_refs.
ClearedAllSoftRefs casr(clear_all_softrefs, heap->collector_policy());
PSYoungGen* young_gen = heap->young_gen();
PSOldGen* old_gen = heap->old_gen();
PSPermGen* perm_gen = heap->perm_gen();
......@@ -275,7 +279,8 @@ void PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
old_gen->max_gen_size(),
max_eden_size,
true /* full gc*/,
gc_cause);
gc_cause,
heap->collector_policy());
heap->resize_old_gen(size_policy->calculated_old_free_size_in_bytes());
......@@ -326,19 +331,6 @@ void PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
// Track memory usage and detect low memory
MemoryService::track_memory_usage();
heap->update_counters();
if (PrintGCDetails) {
if (size_policy->print_gc_time_limit_would_be_exceeded()) {
if (size_policy->gc_time_limit_exceeded()) {
gclog_or_tty->print_cr(" GC time is exceeding GCTimeLimit "
"of %d%%", GCTimeLimit);
} else {
gclog_or_tty->print_cr(" GC time would exceed GCTimeLimit "
"of %d%%", GCTimeLimit);
}
}
size_policy->set_print_gc_time_limit_would_be_exceeded(false);
}
}
if (VerifyAfterGC && heap->total_collections() >= VerifyGCStartAt) {
......
/*
* Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2005-2010 Sun Microsystems, 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
......@@ -1923,31 +1923,32 @@ void PSParallelCompact::summary_phase(ParCompactionManager* cm,
//
// Note that this method should only be called from the vm_thread while at a
// safepoint.
//
// Note that the all_soft_refs_clear flag in the collector policy
// may be true because this method can be called without intervening
// activity. For example when the heap space is tight and full measure
// are being taken to free space.
void PSParallelCompact::invoke(bool maximum_heap_compaction) {
assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
assert(Thread::current() == (Thread*)VMThread::vm_thread(),
"should be in vm thread");
ParallelScavengeHeap* heap = gc_heap();
GCCause::Cause gc_cause = heap->gc_cause();
assert(!heap->is_gc_active(), "not reentrant");
PSAdaptiveSizePolicy* policy = heap->size_policy();
IsGCActiveMark mark;
// Before each allocation/collection attempt, find out from the
// policy object if GCs are, on the whole, taking too long. If so,
// bail out without attempting a collection. The exceptions are
// for explicitly requested GC's.
if (!policy->gc_time_limit_exceeded() ||
GCCause::is_user_requested_gc(gc_cause) ||
GCCause::is_serviceability_requested_gc(gc_cause)) {
IsGCActiveMark mark;
if (ScavengeBeforeFullGC) {
PSScavenge::invoke_no_policy();
}
if (ScavengeBeforeFullGC) {
PSScavenge::invoke_no_policy();
}
const bool clear_all_soft_refs =
heap->collector_policy()->should_clear_all_soft_refs();
PSParallelCompact::invoke_no_policy(maximum_heap_compaction);
}
PSParallelCompact::invoke_no_policy(clear_all_soft_refs ||
maximum_heap_compaction);
}
bool ParallelCompactData::region_contains(size_t region_index, HeapWord* addr) {
......@@ -1976,6 +1977,11 @@ void PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
PSPermGen* perm_gen = heap->perm_gen();
PSAdaptiveSizePolicy* size_policy = heap->size_policy();
// The scope of casr should end after code that can change
// CollectorPolicy::_should_clear_all_soft_refs.
ClearedAllSoftRefs casr(maximum_heap_compaction,
heap->collector_policy());
if (ZapUnusedHeapArea) {
// Save information needed to minimize mangling
heap->record_gen_tops_before_GC();
......@@ -2109,7 +2115,8 @@ void PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
old_gen->max_gen_size(),
max_eden_size,
true /* full gc*/,
gc_cause);
gc_cause,
heap->collector_policy());
heap->resize_old_gen(
size_policy->calculated_old_free_size_in_bytes());
......@@ -2157,19 +2164,6 @@ void PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
// Track memory usage and detect low memory
MemoryService::track_memory_usage();
heap->update_counters();
if (PrintGCDetails) {
if (size_policy->print_gc_time_limit_would_be_exceeded()) {
if (size_policy->gc_time_limit_exceeded()) {
gclog_or_tty->print_cr(" GC time is exceeding GCTimeLimit "
"of %d%%", GCTimeLimit);
} else {
gclog_or_tty->print_cr(" GC time would exceed GCTimeLimit "
"of %d%%", GCTimeLimit);
}
}
size_policy->set_print_gc_time_limit_would_be_exceeded(false);
}
}
if (VerifyAfterGC && heap->total_collections() >= VerifyGCStartAt) {
......
/*
* Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2002-2010 Sun Microsystems, 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
......@@ -187,8 +187,7 @@ void PSRefProcTaskExecutor::execute(EnqueueTask& task)
//
// Note that this method should only be called from the vm_thread while
// at a safepoint!
void PSScavenge::invoke()
{
void PSScavenge::invoke() {
assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
assert(Thread::current() == (Thread*)VMThread::vm_thread(), "should be in vm thread");
assert(!Universe::heap()->is_gc_active(), "not reentrant");
......@@ -197,29 +196,25 @@ void PSScavenge::invoke()
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
PSAdaptiveSizePolicy* policy = heap->size_policy();
IsGCActiveMark mark;
// Before each allocation/collection attempt, find out from the
// policy object if GCs are, on the whole, taking too long. If so,
// bail out without attempting a collection.
if (!policy->gc_time_limit_exceeded()) {
IsGCActiveMark mark;
bool scavenge_was_done = PSScavenge::invoke_no_policy();
bool scavenge_was_done = PSScavenge::invoke_no_policy();
PSGCAdaptivePolicyCounters* counters = heap->gc_policy_counters();
PSGCAdaptivePolicyCounters* counters = heap->gc_policy_counters();
if (UsePerfData)
counters->update_full_follows_scavenge(0);
if (!scavenge_was_done ||
policy->should_full_GC(heap->old_gen()->free_in_bytes())) {
if (UsePerfData)
counters->update_full_follows_scavenge(0);
if (!scavenge_was_done ||
policy->should_full_GC(heap->old_gen()->free_in_bytes())) {
if (UsePerfData)
counters->update_full_follows_scavenge(full_follows_scavenge);
GCCauseSetter gccs(heap, GCCause::_adaptive_size_policy);
if (UseParallelOldGC) {
PSParallelCompact::invoke_no_policy(false);
} else {
PSMarkSweep::invoke_no_policy(false);
}
counters->update_full_follows_scavenge(full_follows_scavenge);
GCCauseSetter gccs(heap, GCCause::_adaptive_size_policy);
CollectorPolicy* cp = heap->collector_policy();
const bool clear_all_softrefs = cp->should_clear_all_soft_refs();
if (UseParallelOldGC) {
PSParallelCompact::invoke_no_policy(clear_all_softrefs);
} else {
PSMarkSweep::invoke_no_policy(clear_all_softrefs);
}
}
}
......@@ -447,6 +442,9 @@ bool PSScavenge::invoke_no_policy() {
size_t promoted = old_gen->used_in_bytes() - old_gen_used_before;
size_policy->update_averages(_survivor_overflow, survived, promoted);
// A successful scavenge should restart the GC time limit count which is
// for full GC's.
size_policy->reset_gc_overhead_limit_count();
if (UseAdaptiveSizePolicy) {
// Calculate the new survivor size and tenuring threshold
......@@ -523,7 +521,8 @@ bool PSScavenge::invoke_no_policy() {
old_gen->max_gen_size(),
max_eden_size,
false /* full gc*/,
gc_cause);
gc_cause,
heap->collector_policy());
}
// Resize the young generation at every collection
......
/*
* Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2004-2010 Sun Microsystems, 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
......@@ -44,13 +44,15 @@ AdaptiveSizePolicy::AdaptiveSizePolicy(size_t init_eden_size,
_survivor_size(init_survivor_size),
_gc_pause_goal_sec(gc_pause_goal_sec),
_throughput_goal(1.0 - double(1.0 / (1.0 + (double) gc_cost_ratio))),
_gc_time_limit_exceeded(false),
_print_gc_time_limit_would_be_exceeded(false),
_gc_time_limit_count(0),
_gc_overhead_limit_exceeded(false),
_print_gc_overhead_limit_would_be_exceeded(false),
_gc_overhead_limit_count(0),
_latest_minor_mutator_interval_seconds(0),
_threshold_tolerance_percent(1.0 + ThresholdTolerance/100.0),
_young_gen_change_for_minor_throughput(0),
_old_gen_change_for_major_throughput(0) {
assert(AdaptiveSizePolicyGCTimeLimitThreshold > 0,
"No opportunity to clear SoftReferences before GC overhead limit");
_avg_minor_pause =
new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding);
_avg_minor_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
......@@ -278,6 +280,147 @@ void AdaptiveSizePolicy::clear_generation_free_space_flags() {
set_decide_at_full_gc(0);
}
void AdaptiveSizePolicy::check_gc_overhead_limit(
size_t young_live,
size_t eden_live,
size_t max_old_gen_size,
size_t max_eden_size,
bool is_full_gc,
GCCause::Cause gc_cause,
CollectorPolicy* collector_policy) {
// Ignore explicit GC's. Exiting here does not set the flag and
// does not reset the count. Updating of the averages for system
// GC's is still controlled by UseAdaptiveSizePolicyWithSystemGC.
if (GCCause::is_user_requested_gc(gc_cause) ||
GCCause::is_serviceability_requested_gc(gc_cause)) {
return;
}
// eden_limit is the upper limit on the size of eden based on
// the maximum size of the young generation and the sizes
// of the survivor space.
// The question being asked is whether the gc costs are high
// and the space being recovered by a collection is low.
// free_in_young_gen is the free space in the young generation
// after a collection and promo_live is the free space in the old
// generation after a collection.
//
// Use the minimum of the current value of the live in the
// young gen or the average of the live in the young gen.
// If the current value drops quickly, that should be taken
// into account (i.e., don't trigger if the amount of free
// space has suddenly jumped up). If the current is much
// higher than the average, use the average since it represents
// the longer term behavor.
const size_t live_in_eden =
MIN2(eden_live, (size_t) avg_eden_live()->average());
const size_t free_in_eden = max_eden_size > live_in_eden ?
max_eden_size - live_in_eden : 0;
const size_t free_in_old_gen = (size_t)(max_old_gen_size - avg_old_live()->average());
const size_t total_free_limit = free_in_old_gen + free_in_eden;
const size_t total_mem = max_old_gen_size + max_eden_size;
const double mem_free_limit = total_mem * (GCHeapFreeLimit/100.0);
const double mem_free_old_limit = max_old_gen_size * (GCHeapFreeLimit/100.0);
const double mem_free_eden_limit = max_eden_size * (GCHeapFreeLimit/100.0);
const double gc_cost_limit = GCTimeLimit/100.0;
size_t promo_limit = (size_t)(max_old_gen_size - avg_old_live()->average());
// But don't force a promo size below the current promo size. Otherwise,
// the promo size will shrink for no good reason.
promo_limit = MAX2(promo_limit, _promo_size);
if (PrintAdaptiveSizePolicy && (Verbose ||
(free_in_old_gen < (size_t) mem_free_old_limit &&
free_in_eden < (size_t) mem_free_eden_limit))) {
gclog_or_tty->print_cr(
"PSAdaptiveSizePolicy::compute_generation_free_space limits:"
" promo_limit: " SIZE_FORMAT
" max_eden_size: " SIZE_FORMAT
" total_free_limit: " SIZE_FORMAT
" max_old_gen_size: " SIZE_FORMAT
" max_eden_size: " SIZE_FORMAT
" mem_free_limit: " SIZE_FORMAT,
promo_limit, max_eden_size, total_free_limit,
max_old_gen_size, max_eden_size,
(size_t) mem_free_limit);
}
bool print_gc_overhead_limit_would_be_exceeded = false;
if (is_full_gc) {
if (gc_cost() > gc_cost_limit &&
free_in_old_gen < (size_t) mem_free_old_limit &&
free_in_eden < (size_t) mem_free_eden_limit) {
// Collections, on average, are taking too much time, and
// gc_cost() > gc_cost_limit
// we have too little space available after a full gc.
// total_free_limit < mem_free_limit
// where
// total_free_limit is the free space available in
// both generations
// total_mem is the total space available for allocation
// in both generations (survivor spaces are not included
// just as they are not included in eden_limit).
// mem_free_limit is a fraction of total_mem judged to be an
// acceptable amount that is still unused.
// The heap can ask for the value of this variable when deciding
// whether to thrown an OutOfMemory error.
// Note that the gc time limit test only works for the collections
// of the young gen + tenured gen and not for collections of the
// permanent gen. That is because the calculation of the space
// freed by the collection is the free space in the young gen +
// tenured gen.
// At this point the GC overhead limit is being exceeded.
inc_gc_overhead_limit_count();
if (UseGCOverheadLimit) {
if (gc_overhead_limit_count() >=
AdaptiveSizePolicyGCTimeLimitThreshold){
// All conditions have been met for throwing an out-of-memory
set_gc_overhead_limit_exceeded(true);
// Avoid consecutive OOM due to the gc time limit by resetting
// the counter.
reset_gc_overhead_limit_count();
} else {
// The required consecutive collections which exceed the
// GC time limit may or may not have been reached. We
// are approaching that condition and so as not to
// throw an out-of-memory before all SoftRef's have been
// cleared, set _should_clear_all_soft_refs in CollectorPolicy.
// The clearing will be done on the next GC.
bool near_limit = gc_overhead_limit_near();
if (near_limit) {
collector_policy->set_should_clear_all_soft_refs(true);
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr(" Nearing GC overhead limit, "
"will be clearing all SoftReference");
}
}
}
}
// Set this even when the overhead limit will not
// cause an out-of-memory. Diagnostic message indicating
// that the overhead limit is being exceeded is sometimes
// printed.
print_gc_overhead_limit_would_be_exceeded = true;
} else {
// Did not exceed overhead limits
reset_gc_overhead_limit_count();
}
}
if (UseGCOverheadLimit && PrintGCDetails && Verbose) {
if (gc_overhead_limit_exceeded()) {
gclog_or_tty->print_cr(" GC is exceeding overhead limit "
"of %d%%", GCTimeLimit);
reset_gc_overhead_limit_count();
} else if (print_gc_overhead_limit_would_be_exceeded) {
assert(gc_overhead_limit_count() > 0, "Should not be printing");
gclog_or_tty->print_cr(" GC would exceed overhead limit "
"of %d%% %d consecutive time(s)",
GCTimeLimit, gc_overhead_limit_count());
}
}
}
// Printing
bool AdaptiveSizePolicy::print_adaptive_size_policy_on(outputStream* st) const {
......
/*
* Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2004-2010 Sun Microsystems, 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
......@@ -27,6 +27,7 @@
// Forward decls
class elapsedTimer;
class CollectorPolicy;
class AdaptiveSizePolicy : public CHeapObj {
friend class GCAdaptivePolicyCounters;
......@@ -75,13 +76,16 @@ class AdaptiveSizePolicy : public CHeapObj {
// This is a hint for the heap: we've detected that gc times
// are taking longer than GCTimeLimit allows.
bool _gc_time_limit_exceeded;
// Use for diagnostics only. If UseGCTimeLimit is false,
bool _gc_overhead_limit_exceeded;
// Use for diagnostics only. If UseGCOverheadLimit is false,
// this variable is still set.
bool _print_gc_time_limit_would_be_exceeded;
bool _print_gc_overhead_limit_would_be_exceeded;
// Count of consecutive GC that have exceeded the
// GC time limit criterion.
uint _gc_time_limit_count;
uint _gc_overhead_limit_count;
// This flag signals that GCTimeLimit is being exceeded
// but may not have done so for the required number of consequetive
// collections.
// Minor collection timers used to determine both
// pause and interval times for collections.
......@@ -406,22 +410,21 @@ class AdaptiveSizePolicy : public CHeapObj {
// Most heaps will choose to throw an OutOfMemoryError when
// this occurs but it is up to the heap to request this information
// of the policy
bool gc_time_limit_exceeded() {
return _gc_time_limit_exceeded;
bool gc_overhead_limit_exceeded() {
return _gc_overhead_limit_exceeded;
}
void set_gc_time_limit_exceeded(bool v) {
_gc_time_limit_exceeded = v;
}
bool print_gc_time_limit_would_be_exceeded() {
return _print_gc_time_limit_would_be_exceeded;
}
void set_print_gc_time_limit_would_be_exceeded(bool v) {
_print_gc_time_limit_would_be_exceeded = v;
void set_gc_overhead_limit_exceeded(bool v) {
_gc_overhead_limit_exceeded = v;
}
uint gc_time_limit_count() { return _gc_time_limit_count; }
void reset_gc_time_limit_count() { _gc_time_limit_count = 0; }
void inc_gc_time_limit_count() { _gc_time_limit_count++; }
// Tests conditions indicate the GC overhead limit is being approached.
bool gc_overhead_limit_near() {
return gc_overhead_limit_count() >=
(AdaptiveSizePolicyGCTimeLimitThreshold - 1);
}
uint gc_overhead_limit_count() { return _gc_overhead_limit_count; }
void reset_gc_overhead_limit_count() { _gc_overhead_limit_count = 0; }
void inc_gc_overhead_limit_count() { _gc_overhead_limit_count++; }
// accessors for flags recording the decisions to resize the
// generations to meet the pause goal.
......@@ -436,6 +439,16 @@ class AdaptiveSizePolicy : public CHeapObj {
int decide_at_full_gc() { return _decide_at_full_gc; }
void set_decide_at_full_gc(int v) { _decide_at_full_gc = v; }
// Check the conditions for an out-of-memory due to excessive GC time.
// Set _gc_overhead_limit_exceeded if all the conditions have been met.
void check_gc_overhead_limit(size_t young_live,
size_t eden_live,
size_t max_old_gen_size,
size_t max_eden_size,
bool is_full_gc,
GCCause::Cause gc_cause,
CollectorPolicy* collector_policy);
// Printing support
virtual bool print_adaptive_size_policy_on(outputStream* st) const;
bool print_adaptive_size_policy_on(outputStream* st, int
......
/*
* Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2005-2010 Sun Microsystems, 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
......@@ -89,8 +89,19 @@ class VM_GC_Operation: public VM_Operation {
if (full) {
_full_gc_count_before = full_gc_count_before;
}
// In ParallelScavengeHeap::mem_allocate() collections can be
// executed within a loop and _all_soft_refs_clear can be set
// true after they have been cleared by a collection and another
// collection started so that _all_soft_refs_clear can be true
// when this collection is started. Don't assert that
// _all_soft_refs_clear have to be false here even though
// mutators have run. Soft refs will be cleared again in this
// collection.
}
~VM_GC_Operation() {
CollectedHeap* ch = Universe::heap();
ch->collector_policy()->set_all_soft_refs_clear(false);
}
~VM_GC_Operation() {}
// Acquire the reference synchronization lock
virtual bool doit_prologue();
......
/*
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2001-2010 Sun Microsystems, 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,6 +31,7 @@ class BarrierSet;
class ThreadClosure;
class AdaptiveSizePolicy;
class Thread;
class CollectorPolicy;
//
// CollectedHeap
......@@ -506,6 +507,9 @@ class CollectedHeap : public CHeapObj {
// Return the AdaptiveSizePolicy for the heap.
virtual AdaptiveSizePolicy* size_policy() = 0;
// Return the CollectorPolicy for the heap
virtual CollectorPolicy* collector_policy() const = 0;
// Iterate over all the ref-containing fields of all objects, calling
// "cl.do_oop" on each. This includes objects in permanent memory.
virtual void oop_iterate(OopClosure* cl) = 0;
......
/*
* Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2001-2010 Sun Microsystems, 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
......@@ -112,6 +112,11 @@ void CollectorPolicy::initialize_perm_generation(PermGen::Name pgnm) {
}
}
bool CollectorPolicy::use_should_clear_all_soft_refs(bool v) {
bool result = _should_clear_all_soft_refs;
set_should_clear_all_soft_refs(false);
return result;
}
GenRemSet* CollectorPolicy::create_rem_set(MemRegion whole_heap,
int max_covered_regions) {
......@@ -126,6 +131,17 @@ GenRemSet* CollectorPolicy::create_rem_set(MemRegion whole_heap,
}
}
void CollectorPolicy::cleared_all_soft_refs() {
// If near gc overhear limit, continue to clear SoftRefs. SoftRefs may
// have been cleared in the last collection but if the gc overhear
// limit continues to be near, SoftRefs should still be cleared.
if (size_policy() != NULL) {
_should_clear_all_soft_refs = size_policy()->gc_overhead_limit_near();
}
_all_soft_refs_clear = true;
}
// GenCollectorPolicy methods.
size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) {
......@@ -489,6 +505,12 @@ HeapWord* GenCollectorPolicy::mem_allocate_work(size_t size,
debug_only(gch->check_for_valid_allocation_state());
assert(gch->no_gc_in_progress(), "Allocation during gc not allowed");
// In general gc_overhead_limit_was_exceeded should be false so
// set it so here and reset it to true only if the gc time
// limit is being exceeded as checked below.
*gc_overhead_limit_was_exceeded = false;
HeapWord* result = NULL;
// Loop until the allocation is satisified,
......@@ -524,12 +546,6 @@ HeapWord* GenCollectorPolicy::mem_allocate_work(size_t size,
return result;
}
// There are NULL's returned for different circumstances below.
// In general gc_overhead_limit_was_exceeded should be false so
// set it so here and reset it to true only if the gc time
// limit is being exceeded as checked below.
*gc_overhead_limit_was_exceeded = false;
if (GC_locker::is_active_and_needs_gc()) {
if (is_tlab) {
return NULL; // Caller will retry allocating individual object
......@@ -568,18 +584,6 @@ HeapWord* GenCollectorPolicy::mem_allocate_work(size_t size,
gc_count_before = Universe::heap()->total_collections();
}
// Allocation has failed and a collection is about
// to be done. If the gc time limit was exceeded the
// last time a collection was done, return NULL so
// that an out-of-memory will be thrown. Clear
// gc_time_limit_exceeded so that subsequent attempts
// at a collection will be made.
if (size_policy()->gc_time_limit_exceeded()) {
*gc_overhead_limit_was_exceeded = true;
size_policy()->set_gc_time_limit_exceeded(false);
return NULL;
}
VM_GenCollectForAllocation op(size,
is_tlab,
gc_count_before);
......@@ -590,6 +594,24 @@ HeapWord* GenCollectorPolicy::mem_allocate_work(size_t size,
assert(result == NULL, "must be NULL if gc_locked() is true");
continue; // retry and/or stall as necessary
}
// Allocation has failed and a collection
// has been done. If the gc time limit was exceeded the
// this time, return NULL so that an out-of-memory
// will be thrown. Clear gc_overhead_limit_exceeded
// so that the overhead exceeded does not persist.
const bool limit_exceeded = size_policy()->gc_overhead_limit_exceeded();
const bool softrefs_clear = all_soft_refs_clear();
assert(!limit_exceeded || softrefs_clear, "Should have been cleared");
if (limit_exceeded && softrefs_clear) {
*gc_overhead_limit_was_exceeded = true;
size_policy()->set_gc_overhead_limit_exceeded(false);
if (op.result() != NULL) {
CollectedHeap::fill_with_object(op.result(), size);
}
return NULL;
}
assert(result == NULL || gch->is_in_reserved(result),
"result not in heap");
return result;
......@@ -688,6 +710,9 @@ HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size,
return result;
}
assert(!should_clear_all_soft_refs(),
"Flag should have been handled and cleared prior to this point");
// What else? We might try synchronous finalization later. If the total
// space available is large enough for the allocation, then a more
// complete compaction phase than we've tried so far might be
......
/*
* Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2001-2010 Sun Microsystems, 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
......@@ -69,12 +69,28 @@ class CollectorPolicy : public CHeapObj {
size_t _min_alignment;
size_t _max_alignment;
// The sizing of the heap are controlled by a sizing policy.
AdaptiveSizePolicy* _size_policy;
// Set to true when policy wants soft refs cleared.
// Reset to false by gc after it clears all soft refs.
bool _should_clear_all_soft_refs;
// Set to true by the GC if the just-completed gc cleared all
// softrefs. This is set to true whenever a gc clears all softrefs, and
// set to false each time gc returns to the mutator. For example, in the
// ParallelScavengeHeap case the latter would be done toward the end of
// mem_allocate() where it returns op.result()
bool _all_soft_refs_clear;
CollectorPolicy() :
_min_alignment(1),
_max_alignment(1),
_initial_heap_byte_size(0),
_max_heap_byte_size(0),
_min_heap_byte_size(0)
_min_heap_byte_size(0),
_size_policy(NULL),
_should_clear_all_soft_refs(false),
_all_soft_refs_clear(false)
{}
public:
......@@ -98,6 +114,19 @@ class CollectorPolicy : public CHeapObj {
G1CollectorPolicyKind
};
AdaptiveSizePolicy* size_policy() { return _size_policy; }
bool should_clear_all_soft_refs() { return _should_clear_all_soft_refs; }
void set_should_clear_all_soft_refs(bool v) { _should_clear_all_soft_refs = v; }
// Returns the current value of _should_clear_all_soft_refs.
// _should_clear_all_soft_refs is set to false as a side effect.
bool use_should_clear_all_soft_refs(bool v);
bool all_soft_refs_clear() { return _all_soft_refs_clear; }
void set_all_soft_refs_clear(bool v) { _all_soft_refs_clear = v; }
// Called by the GC after Soft Refs have been cleared to indicate
// that the request in _should_clear_all_soft_refs has been fulfilled.
void cleared_all_soft_refs();
// Identification methods.
virtual GenCollectorPolicy* as_generation_policy() { return NULL; }
virtual TwoGenerationCollectorPolicy* as_two_generation_policy() { return NULL; }
......@@ -165,6 +194,22 @@ class CollectorPolicy : public CHeapObj {
};
class ClearedAllSoftRefs : public StackObj {
bool _clear_all_soft_refs;
CollectorPolicy* _collector_policy;
public:
ClearedAllSoftRefs(bool clear_all_soft_refs,
CollectorPolicy* collector_policy) :
_clear_all_soft_refs(clear_all_soft_refs),
_collector_policy(collector_policy) {}
~ClearedAllSoftRefs() {
if (_clear_all_soft_refs) {
_collector_policy->cleared_all_soft_refs();
}
}
};
class GenCollectorPolicy : public CollectorPolicy {
protected:
size_t _min_gen0_size;
......@@ -173,10 +218,6 @@ class GenCollectorPolicy : public CollectorPolicy {
GenerationSpec **_generations;
// The sizing of the different generations in the heap are controlled
// by a sizing policy.
AdaptiveSizePolicy* _size_policy;
// Return true if an allocation should be attempted in the older
// generation if it fails in the younger generation. Return
// false, otherwise.
......@@ -236,14 +277,11 @@ class GenCollectorPolicy : public CollectorPolicy {
virtual size_t large_typearray_limit();
// Adaptive size policy
AdaptiveSizePolicy* size_policy() { return _size_policy; }
virtual void initialize_size_policy(size_t init_eden_size,
size_t init_promo_size,
size_t init_survivor_size);
};
// All of hotspot's current collectors are subtypes of this
// class. Currently, these collectors all use the same gen[0],
// but have different gen[1] types. If we add another subtype
......
/*
* Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2001-2010 Sun Microsystems, 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
......@@ -594,6 +594,10 @@ void DefNewGeneration::collect(bool full,
_tenuring_threshold =
age_table()->compute_tenuring_threshold(to()->capacity()/HeapWordSize);
// A successful scavenge should restart the GC time limit count which is
// for full GC's.
AdaptiveSizePolicy* size_policy = gch->gen_policy()->size_policy();
size_policy->reset_gc_overhead_limit_count();
if (PrintGC && !PrintGCDetails) {
gch->print_heap_change(gch_prev_used);
}
......
/*
* Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2000-2010 Sun Microsystems, 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
......@@ -428,7 +428,8 @@ void GenCollectedHeap::do_collection(bool full,
assert(my_thread->is_VM_thread() ||
my_thread->is_ConcurrentGC_thread(),
"incorrect thread type capability");
assert(Heap_lock->is_locked(), "the requesting thread should have the Heap_lock");
assert(Heap_lock->is_locked(),
"the requesting thread should have the Heap_lock");
guarantee(!is_gc_active(), "collection is not reentrant");
assert(max_level < n_gens(), "sanity check");
......@@ -436,6 +437,11 @@ void GenCollectedHeap::do_collection(bool full,
return; // GC is disabled (e.g. JNI GetXXXCritical operation)
}
const bool do_clear_all_soft_refs = clear_all_soft_refs ||
collector_policy()->should_clear_all_soft_refs();
ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy());
const size_t perm_prev_used = perm_gen()->used();
if (PrintHeapAtGC) {
......@@ -560,11 +566,11 @@ void GenCollectedHeap::do_collection(bool full,
if (rp->discovery_is_atomic()) {
rp->verify_no_references_recorded();
rp->enable_discovery();
rp->setup_policy(clear_all_soft_refs);
rp->setup_policy(do_clear_all_soft_refs);
} else {
// collect() below will enable discovery as appropriate
}
_gens[i]->collect(full, clear_all_soft_refs, size, is_tlab);
_gens[i]->collect(full, do_clear_all_soft_refs, size, is_tlab);
if (!rp->enqueuing_is_done()) {
rp->enqueue_discovered_references();
} else {
......
/*
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2001-2010 Sun Microsystems, 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
......@@ -29,6 +29,13 @@ void GenMarkSweep::invoke_at_safepoint(int level, ReferenceProcessor* rp,
bool clear_all_softrefs) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
GenCollectedHeap* gch = GenCollectedHeap::heap();
#ifdef ASSERT
if (gch->collector_policy()->should_clear_all_soft_refs()) {
assert(clear_all_softrefs, "Policy should have been checked earlier");
}
#endif
// hook up weak ref data so it can be used during Mark-Sweep
assert(ref_processor() == NULL, "no stomping");
assert(rp != NULL, "should be non-NULL");
......@@ -44,7 +51,6 @@ void GenMarkSweep::invoke_at_safepoint(int level, ReferenceProcessor* rp,
// Increment the invocation count for the permanent generation, since it is
// implicitly collected whenever we do a full mark sweep collection.
GenCollectedHeap* gch = GenCollectedHeap::heap();
gch->perm_gen()->stat_record()->invocations++;
// Capture heap size before collection for printing.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册