< prev index next >
src/hotspot/share/gc/z/zPageCache.cpp
Print this page
@@ -1,7 +1,7 @@
/*
- * 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
@@ -20,33 +20,43 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "precompiled.hpp"
+#include "gc/z/zGlobals.hpp"
#include "gc/z/zList.inline.hpp"
#include "gc/z/zNUMA.hpp"
#include "gc/z/zPage.inline.hpp"
#include "gc/z/zPageCache.hpp"
#include "gc/z/zStat.hpp"
#include "gc/z/zValue.inline.hpp"
+#include "jfr/jfrEvents.hpp"
#include "logging/log.hpp"
+#include "memory/allocation.hpp"
static const ZStatCounter ZCounterPageCacheHitL1("Memory", "Page Cache Hit L1", ZStatUnitOpsPerSecond);
static const ZStatCounter ZCounterPageCacheHitL2("Memory", "Page Cache Hit L2", ZStatUnitOpsPerSecond);
static const ZStatCounter ZCounterPageCacheHitL3("Memory", "Page Cache Hit L3", ZStatUnitOpsPerSecond);
static const ZStatCounter ZCounterPageCacheMiss("Memory", "Page Cache Miss", ZStatUnitOpsPerSecond);
+class ZPageCacheFlushClosure : public StackObj {
+ friend class ZPageCache;
+
+protected:
+ const size_t _requested;
+ size_t _flushed;
+
+public:
+ ZPageCacheFlushClosure(size_t requested);
+ virtual bool do_page(const ZPage* page) = 0;
+};
+
ZPageCacheFlushClosure::ZPageCacheFlushClosure(size_t requested) :
_requested(requested),
_flushed(0) {}
-size_t ZPageCacheFlushClosure::overflushed() const {
- return _flushed > _requested ? _flushed - _requested : 0;
-}
-
ZPageCache::ZPageCache() :
- _available(0),
_small(),
_medium(),
_large() {}
ZPage* ZPageCache::alloc_small_page() {
@@ -159,52 +169,44 @@
if (size < oversized->size()) {
// Split oversized page
page = oversized->split(type, size);
// Cache remainder
- free_page_inner(oversized);
+ free_page(oversized);
} else {
// Re-type correctly sized page
page = oversized->retype(type);
}
}
}
- if (page != NULL) {
- _available -= page->size();
- } else {
+ if (page == NULL) {
ZStatInc(ZCounterPageCacheMiss);
}
return page;
}
-void ZPageCache::free_page_inner(ZPage* page) {
+void ZPageCache::free_page(ZPage* page) {
const uint8_t type = page->type();
if (type == ZPageTypeSmall) {
_small.get(page->numa_id()).insert_first(page);
} else if (type == ZPageTypeMedium) {
_medium.insert_first(page);
} else {
_large.insert_first(page);
}
}
-void ZPageCache::free_page(ZPage* page) {
- free_page_inner(page);
- _available += page->size();
-}
-
bool ZPageCache::flush_list_inner(ZPageCacheFlushClosure* cl, ZList<ZPage>* from, ZList<ZPage>* to) {
ZPage* const page = from->last();
if (page == NULL || !cl->do_page(page)) {
// Don't flush page
return false;
}
// Flush page
- _available -= page->size();
from->remove(page);
to->insert_last(page);
return true;
}
@@ -237,10 +239,94 @@
void ZPageCache::flush(ZPageCacheFlushClosure* cl, ZList<ZPage>* to) {
// Prefer flushing large, then medium and last small pages
flush_list(cl, &_large, to);
flush_list(cl, &_medium, to);
flush_per_numa_lists(cl, &_small, to);
+
+ if (cl->_flushed > cl->_requested) {
+ // Overflushed, keep part of last page
+ const size_t overflushed = cl->_flushed - cl->_requested;
+ free_page(to->last()->split(overflushed));
+ cl->_flushed -= overflushed;
+ }
+}
+
+class ZPageCacheFlushForAllocationClosure : public ZPageCacheFlushClosure {
+public:
+ ZPageCacheFlushForAllocationClosure(size_t requested) :
+ ZPageCacheFlushClosure(requested) {}
+
+ virtual bool do_page(const ZPage* page) {
+ if (_flushed < _requested) {
+ // Flush page
+ _flushed += page->size();
+ return true;
+ }
+
+ // Don't flush page
+ return false;
+ }
+};
+
+void ZPageCache::flush_for_allocation(size_t requested, ZList<ZPage>* to) {
+ EventZPageCacheFlush event;
+
+ // Flush
+ ZPageCacheFlushForAllocationClosure cl(requested);
+ flush(&cl, to);
+
+ // Send event
+ event.commit(requested, true /* for_allocation */);
+}
+
+class ZPageCacheFlushForUncommitClosure : public ZPageCacheFlushClosure {
+private:
+ const uint64_t _now;
+ const uint64_t _delay;
+ uint64_t* _timeout;
+
+public:
+ ZPageCacheFlushForUncommitClosure(size_t requested, uint64_t delay, uint64_t* timeout) :
+ ZPageCacheFlushClosure(requested),
+ _now(os::elapsedTime()),
+ _delay(delay),
+ _timeout(timeout) {}
+
+ virtual bool do_page(const ZPage* page) {
+ const uint64_t expires = page->last_used() + _delay;
+ const uint64_t timeout = expires - MIN2(expires, _now);
+
+ if (_flushed < _requested && timeout == 0) {
+ // Flush page
+ _flushed += page->size();
+ return true;
+ }
+
+ // Record shortest non-expired timeout
+ *_timeout = MIN2(*_timeout, timeout);
+
+ // Don't flush page
+ return false;
+ }
+};
+
+size_t ZPageCache::flush_for_uncommit(size_t requested, uint64_t delay, uint64_t* timeout, ZList<ZPage>* to) {
+ if (requested == 0) {
+ // Nothing to flush
+ return 0;
+ }
+
+ EventZPageCacheFlush event;
+
+ // Flush
+ ZPageCacheFlushForUncommitClosure cl(requested, delay, timeout);
+ flush(&cl, to);
+
+ // Send event
+ event.commit(requested, false /* for_allocation */);
+
+ return cl._flushed;
}
void ZPageCache::pages_do(ZPageClosure* cl) const {
// Small
ZPerNUMAConstIterator<ZList<ZPage> > iter_numa(&_small);
< prev index next >