RFR(M): 8244660: Code cache sweeper heuristics is broken
Nils Eliasson
nils.eliasson at oracle.com
Wed May 27 20:42:17 UTC 2020
Hi Man,
On 2020-05-22 10:13, Man Cao wrote:
> Hi Nils,
>
> Thanks for the updated code!
> Below is my feedback after a closer look, ordered by importance.
>
> 1. sweeper_loop()
> NMethodSweeper::sweeper_loop() seems to be missing an inner loop to
> check for a wakeup condition.
> It could suffer from lost wakeup and spurious wakeup problems, as
> described in [1].
> Similar code like ServiceThread::service_thread_entry() also has
> nested loops to check for wakeup conditions.
> We could add a boolean variable "should_sweep", guarded by the
> CodeSweeper_lock.
> [1]
> https://www.modernescpp.com/index.php/c-core-guidelines-be-aware-of-the-traps-of-condition-variables
Reasonable.
I re-added _should_sweep and did some minor refactorings.
>
> One wild idea is to let the ServiceThread handle the code cache sweep
> work, and remove the sweeper thread.
> Has anyone considered this idea before?
I think it has but I don't remember the details. Code cache sweeping
would block the service thread for quite some time.
>
> 2. Rank of CodeSweeper_lock
> In mutexLocker.cpp:
> def(CodeSweeper_lock , PaddedMonitor, special+1, true,
> _safepoint_check_never);
>
> Should the rank be "special - 1", like the CompiledMethod_lock?
> We want to check that this lock acquisition order is valid, but not
> vice versa:
> { MonitorLocker(CodeCache_lock); MonitorLocker(CodeSweeper_lock); }
> Reading the code in Mutex::set_owner_implementation(), the deadlock
> avoidance rule enforces that
> the inner lock should have a lower rank than the outer lock.
> "special + 1" has the same value as Mutex::suspend_resume, which
> disables the deadlock avoidance check.
Good catch - but the rank should be "special - 2". There is one code
path through InstanceKlass::add_osr_nmethod that calls make_not_entrant
on an nmethod while holding the CompileMethod_lock. So the rank need to
be one less.
I updated enum lock_types to add one more level of special.
>
> 3. Data race on _bytes_changed
> 74 static volatile int _bytes_changed;
> The "volatile" keyword likely intends to avoid data races and
> atomicity issues,
> but the accesses use "_bytes_changed +=" and "=" to do loads and stores.
> Should those accesses use Atomic::add(&_bytes_changed, value) and
> other Atomic functions.
Fixed.
>
> 4. NMethodSweeper::_sweep_threshold
> Is it better to make it a "size_t" instead of "int"? Then we can use
> "ulong" in metadata.xml, and SIZE_FORMAT in the log_info()).
> Also it's probably better to name it as _sweep_threshold_bytes or
> _sweep_threshold_bytes, to differentiate from the
> SweeperThreshold percentage value.
> _sweep_threshold's type should probably be consistent
> with _bytes_changed, so perhaps _bytes_changed
> could be changed to size_t.
ok, fixed.
>
> 5.
> 887 void CompileBroker::init_compiler_sweeper_threads() {
> 888 NMethodSweeper::set_sweep_threshold((SweeperThreshold / 100) *
> ReservedCodeCacheSize);
> Is it better to use "static_cast<size_t>()" to explicitly mark type cast?
sure.
>
> -Man
New webrev: http://cr.openjdk.java.net/~neliasso/8244660/webrev.03/
Best regards,
Nils
More information about the hotspot-compiler-dev
mailing list