Skip to content
Permalink
Browse files

8241361: ZGC: Implement memory related JFR events

Co-authored-by: Per Liden <per.liden@oracle.com>
Reviewed-by: pliden, eosterlund
  • Loading branch information
stefank and pliden committed Mar 27, 2020
1 parent 6df2370 commit b7439a8ae38d13ce628a8a3b97d7f0c417a02f60
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. 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
@@ -36,6 +36,7 @@
#include "gc/z/zTask.hpp"
#include "gc/z/zTracer.inline.hpp"
#include "gc/z/zWorkers.hpp"
#include "jfr/jfrEvents.hpp"
#include "runtime/globals.hpp"
#include "runtime/init.hpp"
#include "runtime/java.hpp"
@@ -422,6 +423,8 @@ ZPage* ZPageAllocator::alloc_page_common_inner(uint8_t type, size_t size, bool n
}

ZPage* ZPageAllocator::alloc_page_common(uint8_t type, size_t size, ZAllocationFlags flags) {
EventZPageAllocation event;

ZPage* const page = alloc_page_common_inner(type, size, flags.no_reserve());
if (page == NULL) {
// Out of memory
@@ -432,7 +435,8 @@ ZPage* ZPageAllocator::alloc_page_common(uint8_t type, size_t size, ZAllocationF
increase_used(size, flags.relocation());

// Send trace event
ZTracer::tracer()->report_page_alloc(size, _used, max_available(flags.no_reserve()), _cache.available(), flags);
event.commit(type, size, _used, max_available(flags.no_reserve()),
_cache.available(), flags.non_blocking(), flags.no_reserve());

return page;
}
@@ -461,6 +465,7 @@ ZPage* ZPageAllocator::alloc_page_blocking(uint8_t type, size_t size, ZAllocatio
if (page == NULL) {
// Allocation failed
ZStatTimer timer(ZCriticalPhaseAllocationStall);
EventZAllocationStall event;

// We can only block if VM is fully initialized
check_out_of_memory_during_initialization();
@@ -490,6 +495,8 @@ ZPage* ZPageAllocator::alloc_page_blocking(uint8_t type, size_t size, ZAllocatio
ZLocker<ZLock> locker(&_lock);
_satisfied.remove(&request);
}

event.commit(type, size);
}

return page;
@@ -571,7 +578,9 @@ void ZPageAllocator::free_page(ZPage* page, bool reclaimed) {
satisfy_alloc_queue();
}

size_t ZPageAllocator::flush_cache(ZPageCacheFlushClosure* cl) {
size_t ZPageAllocator::flush_cache(ZPageCacheFlushClosure* cl, bool for_allocation) {
EventZPageCacheFlush event;

ZList<ZPage> list;

// Flush pages
@@ -591,6 +600,9 @@ size_t ZPageAllocator::flush_cache(ZPageCacheFlushClosure* cl) {
destroy_page(page);
}

// Send event
event.commit(flushed, for_allocation);

return flushed;
}

@@ -616,7 +628,7 @@ void ZPageAllocator::flush_cache_for_allocation(size_t requested) {

// Flush pages
ZPageCacheFlushForAllocationClosure cl(requested);
const size_t flushed = flush_cache(&cl);
const size_t flushed = flush_cache(&cl, true /* for_allocation */);

assert(requested == flushed, "Failed to flush");

@@ -678,6 +690,7 @@ uint64_t ZPageAllocator::uncommit(uint64_t delay) {
return timeout;
}

EventZUncommit event;
size_t capacity_before;
size_t capacity_after;
size_t uncommitted;
@@ -698,7 +711,7 @@ uint64_t ZPageAllocator::uncommit(uint64_t delay) {
if (flush > 0) {
// Flush pages to uncommit
ZPageCacheFlushForUncommitClosure cl(flush, delay);
uncommit += flush_cache(&cl);
uncommit += flush_cache(&cl, false /* for_allocation */);
timeout = cl.timeout();
}

@@ -717,6 +730,9 @@ uint64_t ZPageAllocator::uncommit(uint64_t delay) {
capacity_after / M, percent_of(capacity_after, max_capacity()),
uncommitted / M);

// Send event
event.commit(capacity_before, capacity_after, uncommitted);

// Update statistics
ZStatInc(ZCounterUncommit, uncommitted);
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. 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
@@ -81,7 +81,7 @@ class ZPageAllocator {
ZPage* alloc_page_blocking(uint8_t type, size_t size, ZAllocationFlags flags);
ZPage* alloc_page_nonblocking(uint8_t type, size_t size, ZAllocationFlags flags);

size_t flush_cache(ZPageCacheFlushClosure* cl);
size_t flush_cache(ZPageCacheFlushClosure* cl, bool for_allocation);
void flush_cache_for_allocation(size_t requested);

void satisfy_alloc_queue();
@@ -26,6 +26,7 @@
#include "gc/z/zPage.inline.hpp"
#include "gc/z/zRelocationSet.hpp"
#include "gc/z/zRelocationSetSelector.inline.hpp"
#include "jfr/jfrEvents.hpp"
#include "logging/log.hpp"
#include "runtime/globals.hpp"
#include "utilities/debug.hpp"
@@ -41,9 +42,11 @@ ZRelocationSetSelectorGroupStats::ZRelocationSetSelectorGroupStats() :
_compacting_to(0) {}

ZRelocationSetSelectorGroup::ZRelocationSetSelectorGroup(const char* name,
uint8_t page_type,
size_t page_size,
size_t object_size_limit) :
_name(name),
_page_type(page_type),
_page_size(page_size),
_object_size_limit(object_size_limit),
_fragmentation_limit(page_size * (ZFragmentationLimit / 100)),
@@ -81,6 +84,16 @@ void ZRelocationSetSelectorGroup::register_garbage_page(ZPage* page) {
_stats._empty += size;
}

bool ZRelocationSetSelectorGroup::is_disabled() {
// Medium pages are disabled when their page size is zero
return _page_type == ZPageTypeMedium && _page_size == 0;
}

bool ZRelocationSetSelectorGroup::is_selectable() {
// Large pages are not selectable
return _page_type != ZPageTypeLarge;
}

void ZRelocationSetSelectorGroup::semi_sort() {
// Semi-sort registered pages by live bytes in ascending order
const size_t npartitions_shift = 11;
@@ -123,12 +136,7 @@ void ZRelocationSetSelectorGroup::semi_sort() {
}
}

void ZRelocationSetSelectorGroup::select() {
if (_page_size == 0) {
// Page type disabled
return;
}

void ZRelocationSetSelectorGroup::select_inner() {
// Calculate the number of pages to relocate by successively including pages in
// a candidate relocation set and calculate the maximum space requirement for
// their live objects.
@@ -177,10 +185,26 @@ void ZRelocationSetSelectorGroup::select() {
_name, selected_from, selected_to, npages - _nselected);
}

void ZRelocationSetSelectorGroup::select() {
if (is_disabled()) {
return;
}

EventZRelocationSetGroup event;

if (is_selectable()) {
select_inner();
}

// Send event
event.commit(_page_type, _stats.npages(), _stats.total(), _stats.empty(),
_stats.compacting_from(), _stats.compacting_to());
}

ZRelocationSetSelector::ZRelocationSetSelector() :
_small("Small", ZPageSizeSmall, ZObjectSizeLimitSmall),
_medium("Medium", ZPageSizeMedium, ZObjectSizeLimitMedium),
_large("Large", 0 /* page_size */, 0 /* object_size_limit */) {}
_small("Small", ZPageTypeSmall, ZPageSizeSmall, ZObjectSizeLimitSmall),
_medium("Medium", ZPageTypeMedium, ZPageSizeMedium, ZObjectSizeLimitMedium),
_large("Large", ZPageTypeLarge, 0 /* page_size */, 0 /* object_size_limit */) {}

void ZRelocationSetSelector::register_live_page(ZPage* page) {
const uint8_t type = page->type();
@@ -213,13 +237,19 @@ void ZRelocationSetSelector::select(ZRelocationSet* relocation_set) {
// bytes in ascending order. Relocating pages in this order allows
// us to start reclaiming memory more quickly.

// Select pages from each group, except large
EventZRelocationSet event;

// Select pages from each group
_large.select();
_medium.select();
_small.select();

// Populate relocation set
relocation_set->populate(_medium.selected(), _medium.nselected(),
_small.selected(), _small.nselected());

// Send event
event.commit(total(), empty(), compacting_from(), compacting_to());
}

ZRelocationSetSelectorStats ZRelocationSetSelector::stats() const {
@@ -71,6 +71,7 @@ class ZRelocationSetSelectorStats {
class ZRelocationSetSelectorGroup {
private:
const char* const _name;
const uint8_t _page_type;
const size_t _page_size;
const size_t _object_size_limit;
const size_t _fragmentation_limit;
@@ -80,10 +81,14 @@ class ZRelocationSetSelectorGroup {
size_t _nselected;
ZRelocationSetSelectorGroupStats _stats;

bool is_disabled();
bool is_selectable();
void semi_sort();
void select_inner();

public:
ZRelocationSetSelectorGroup(const char* name,
uint8_t page_type,
size_t page_size,
size_t object_size_limit);
~ZRelocationSetSelectorGroup();
@@ -104,6 +109,11 @@ class ZRelocationSetSelector : public StackObj {
ZRelocationSetSelectorGroup _medium;
ZRelocationSetSelectorGroup _large;

size_t total() const;
size_t empty() const;
size_t compacting_from() const;
size_t compacting_to() const;

public:
ZRelocationSetSelector();

@@ -78,4 +78,20 @@ inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorGroup::stat
return _stats;
}

inline size_t ZRelocationSetSelector::total() const {
return _small.stats().total() + _medium.stats().total() + _large.stats().total();
}

inline size_t ZRelocationSetSelector::empty() const {
return _small.stats().empty() + _medium.stats().empty() + _large.stats().empty();
}

inline size_t ZRelocationSetSelector::compacting_from() const {
return _small.stats().compacting_from() + _medium.stats().compacting_from() + _large.stats().compacting_from();
}

inline size_t ZRelocationSetSelector::compacting_to() const {
return _small.stats().compacting_to() + _medium.stats().compacting_to() + _large.stats().compacting_to();
}

#endif // SHARE_GC_Z_ZRELOCATIONSETSELECTOR_INLINE_HPP
@@ -1153,7 +1153,9 @@ void ZStatRelocation::print(const char* name, const ZRelocationSetSelectorGroupS

void ZStatRelocation::print() {
print("Small", _stats.small());
print("Medium", _stats.medium());
if (ZPageSizeMedium != 0) {
print("Medium", _stats.medium());
}
print("Large", _stats.large());

log_info(gc, reloc)("Relocation: %s", _success ? "Successful" : "Incomplete");
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@

#include "precompiled.hpp"
#include "gc/shared/gcId.hpp"
#include "gc/z/zGlobals.hpp"
#include "gc/z/zStat.hpp"
#include "gc/z/zTracer.hpp"
#include "jfr/jfrEvents.hpp"
@@ -35,6 +36,19 @@

#if INCLUDE_JFR

class ZPageTypeConstant : public JfrSerializer {
public:
virtual void serialize(JfrCheckpointWriter& writer) {
writer.write_count(3);
writer.write_key(ZPageTypeSmall);
writer.write("Small");
writer.write_key(ZPageTypeMedium);
writer.write("Medium");
writer.write_key(ZPageTypeLarge);
writer.write("Large");
}
};

class ZStatisticsCounterTypeConstant : public JfrSerializer {
public:
virtual void serialize(JfrCheckpointWriter& writer) {
@@ -58,6 +72,9 @@ class ZStatisticsSamplerTypeConstant : public JfrSerializer {
};

static void register_jfr_type_serializers() {
JfrSerializer::register_serializer(TYPE_ZPAGETYPETYPE,
true /* permit_cache */,
new ZPageTypeConstant());
JfrSerializer::register_serializer(TYPE_ZSTATISTICSCOUNTERTYPE,
true /* permit_cache */,
new ZStatisticsCounterTypeConstant());
@@ -114,18 +131,3 @@ void ZTracer::send_thread_phase(const char* name, const Ticks& start, const Tick
e.commit();
}
}

void ZTracer::send_page_alloc(size_t size, size_t used, size_t free, size_t cache, ZAllocationFlags flags) {
NoSafepointVerifier nsv;

EventZPageAllocation e;
if (e.should_commit()) {
e.set_pageSize(size);
e.set_usedAfter(used);
e.set_freeAfter(free);
e.set_inCacheAfter(cache);
e.set_nonBlocking(flags.non_blocking());
e.set_noReserve(flags.no_reserve());
e.commit();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. 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,7 +25,6 @@
#define SHARE_GC_Z_ZTRACER_HPP

#include "gc/shared/gcTrace.hpp"
#include "gc/z/zAllocationFlags.hpp"

class ZStatCounter;
class ZStatPhase;
@@ -40,7 +39,6 @@ class ZTracer : public GCTracer {
void send_stat_counter(const ZStatCounter& counter, uint64_t increment, uint64_t value);
void send_stat_sampler(const ZStatSampler& sampler, uint64_t value);
void send_thread_phase(const char* name, const Ticks& start, const Ticks& end);
void send_page_alloc(size_t size, size_t used, size_t free, size_t cache, ZAllocationFlags flags);

public:
static ZTracer* tracer();
@@ -49,7 +47,6 @@ class ZTracer : public GCTracer {
void report_stat_counter(const ZStatCounter& counter, uint64_t increment, uint64_t value);
void report_stat_sampler(const ZStatSampler& sampler, uint64_t value);
void report_thread_phase(const char* name, const Ticks& start, const Ticks& end);
void report_page_alloc(size_t size, size_t used, size_t free, size_t cache, ZAllocationFlags flags);
};

class ZTraceThreadPhase : public StackObj {

0 comments on commit b7439a8

Please sign in to comment.