diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 0c6397a6e0213ab24be17c18cfda0ed0a72013a5..14046d32c72d0738d45961a74fe51f360ac704b7 100644 --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -2496,7 +2496,8 @@ void CMSCollector::save_heap_summary() { } void CMSCollector::report_heap_summary(GCWhen::Type when) { - _gc_tracer_cm->report_gc_heap_summary(when, _last_heap_summary, _last_metaspace_summary); + _gc_tracer_cm->report_gc_heap_summary(when, _last_heap_summary); + _gc_tracer_cm->report_metaspace_summary(when, _last_metaspace_summary); } void CMSCollector::collect_in_foreground(bool clear_all_soft_refs, GCCause::Cause cause) { diff --git a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp index bb44fbca2a9412ca9a86770ba510cf74365db9fe..8f6fb224226f1984434150f1b3678c0e1cccf6e4 100644 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp @@ -669,8 +669,10 @@ void ParallelScavengeHeap::print_heap_change(size_t prev_used) { void ParallelScavengeHeap::trace_heap(GCWhen::Type when, GCTracer* gc_tracer) { const PSHeapSummary& heap_summary = create_ps_heap_summary(); + gc_tracer->report_gc_heap_summary(when, heap_summary); + const MetaspaceSummary& metaspace_summary = create_metaspace_summary(); - gc_tracer->report_gc_heap_summary(when, heap_summary, metaspace_summary); + gc_tracer->report_metaspace_summary(when, metaspace_summary); } ParallelScavengeHeap* ParallelScavengeHeap::heap() { diff --git a/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp b/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp index 4e79b8f93d50e1c2b72d4480670c8cc1add2d586..7f6dca0fb1fa035e9f2e239e835730203fca1ab5 100644 --- a/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp +++ b/src/share/vm/gc_implementation/shared/gcHeapSummary.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCHEAPSUMMARY_HPP #include "memory/allocation.hpp" +#include "memory/metaspaceChunkFreeListSummary.hpp" class VirtualSpaceSummary : public StackObj { HeapWord* _start; @@ -125,18 +126,49 @@ class PSHeapSummary : public GCHeapSummary { }; class MetaspaceSummary : public StackObj { + size_t _capacity_until_GC; MetaspaceSizes _meta_space; MetaspaceSizes _data_space; MetaspaceSizes _class_space; + MetaspaceChunkFreeListSummary _metaspace_chunk_free_list_summary; + MetaspaceChunkFreeListSummary _class_chunk_free_list_summary; public: - MetaspaceSummary() : _meta_space(), _data_space(), _class_space() {} - MetaspaceSummary(const MetaspaceSizes& meta_space, const MetaspaceSizes& data_space, const MetaspaceSizes& class_space) : - _meta_space(meta_space), _data_space(data_space), _class_space(class_space) { } - + MetaspaceSummary() : + _capacity_until_GC(0), + _meta_space(), + _data_space(), + _class_space(), + _metaspace_chunk_free_list_summary(), + _class_chunk_free_list_summary() + {} + MetaspaceSummary(size_t capacity_until_GC, + const MetaspaceSizes& meta_space, + const MetaspaceSizes& data_space, + const MetaspaceSizes& class_space, + const MetaspaceChunkFreeListSummary& metaspace_chunk_free_list_summary, + const MetaspaceChunkFreeListSummary& class_chunk_free_list_summary) : + _capacity_until_GC(capacity_until_GC), + _meta_space(meta_space), + _data_space(data_space), + _class_space(class_space), + _metaspace_chunk_free_list_summary(metaspace_chunk_free_list_summary), + _class_chunk_free_list_summary(class_chunk_free_list_summary) + {} + + size_t capacity_until_GC() const { return _capacity_until_GC; } const MetaspaceSizes& meta_space() const { return _meta_space; } const MetaspaceSizes& data_space() const { return _data_space; } const MetaspaceSizes& class_space() const { return _class_space; } + + const MetaspaceChunkFreeListSummary& metaspace_chunk_free_list_summary() const { + return _metaspace_chunk_free_list_summary; + } + + const MetaspaceChunkFreeListSummary& class_chunk_free_list_summary() const { + return _class_chunk_free_list_summary; + } + }; #endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_GCHEAPSUMMARY_HPP diff --git a/src/share/vm/gc_implementation/shared/gcTrace.cpp b/src/share/vm/gc_implementation/shared/gcTrace.cpp index 5e533d341d4e2995aac811638eefb3e2fe918eb4..994d468bbc5392d0b6a9f42934797ed610b9f630 100644 --- a/src/share/vm/gc_implementation/shared/gcTrace.cpp +++ b/src/share/vm/gc_implementation/shared/gcTrace.cpp @@ -139,11 +139,21 @@ void GCTracer::report_object_count_after_gc(BoolObjectClosure* is_alive_cl) { } #endif // INCLUDE_SERVICES -void GCTracer::report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const MetaspaceSummary& meta_space_summary) const { +void GCTracer::report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary) const { assert_set_gc_id(); send_gc_heap_summary_event(when, heap_summary); - send_meta_space_summary_event(when, meta_space_summary); +} + +void GCTracer::report_metaspace_summary(GCWhen::Type when, const MetaspaceSummary& summary) const { + assert_set_gc_id(); + + send_meta_space_summary_event(when, summary); + + send_metaspace_chunk_free_list_summary(when, Metaspace::NonClassType, summary.metaspace_chunk_free_list_summary()); + if (UseCompressedClassPointers) { + send_metaspace_chunk_free_list_summary(when, Metaspace::ClassType, summary.class_chunk_free_list_summary()); + } } void YoungGCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) { diff --git a/src/share/vm/gc_implementation/shared/gcTrace.hpp b/src/share/vm/gc_implementation/shared/gcTrace.hpp index fda51e8bf52bbb36fca8c8e59c609d81e7c1537f..3b55211a724893641edfd87e55bcf19027e3dba7 100644 --- a/src/share/vm/gc_implementation/shared/gcTrace.hpp +++ b/src/share/vm/gc_implementation/shared/gcTrace.hpp @@ -30,6 +30,7 @@ #include "gc_implementation/shared/gcWhen.hpp" #include "gc_implementation/shared/copyFailedInfo.hpp" #include "memory/allocation.hpp" +#include "memory/metaspace.hpp" #include "memory/referenceType.hpp" #if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1YCTypes.hpp" @@ -41,6 +42,7 @@ typedef uint GCId; class EvacuationInfo; class GCHeapSummary; +class MetaspaceChunkFreeListSummary; class MetaspaceSummary; class PSHeapSummary; class ReferenceProcessorStats; @@ -124,7 +126,8 @@ class GCTracer : public ResourceObj { public: void report_gc_start(GCCause::Cause cause, const Ticks& timestamp); void report_gc_end(const Ticks& timestamp, TimePartitions* time_partitions); - void report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const MetaspaceSummary& meta_space_summary) const; + void report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary) const; + void report_metaspace_summary(GCWhen::Type when, const MetaspaceSummary& metaspace_summary) const; void report_gc_reference_stats(const ReferenceProcessorStats& rp) const; void report_object_count_after_gc(BoolObjectClosure* object_filter) NOT_SERVICES_RETURN; bool has_reported_gc_start() const; @@ -138,6 +141,7 @@ class GCTracer : public ResourceObj { void send_garbage_collection_event() const; void send_gc_heap_summary_event(GCWhen::Type when, const GCHeapSummary& heap_summary) const; void send_meta_space_summary_event(GCWhen::Type when, const MetaspaceSummary& meta_space_summary) const; + void send_metaspace_chunk_free_list_summary(GCWhen::Type when, Metaspace::MetadataType mdtype, const MetaspaceChunkFreeListSummary& summary) const; void send_reference_stats_event(ReferenceType type, size_t count) const; void send_phase_events(TimePartitions* time_partitions) const; }; diff --git a/src/share/vm/gc_implementation/shared/gcTraceSend.cpp b/src/share/vm/gc_implementation/shared/gcTraceSend.cpp index ecf0731255b045a744bc871b2b4fac2ec71697a5..b7d6e8e6b591dd4aba6ac839c04c74b6a677f9b2 100644 --- a/src/share/vm/gc_implementation/shared/gcTraceSend.cpp +++ b/src/share/vm/gc_implementation/shared/gcTraceSend.cpp @@ -64,6 +64,30 @@ void GCTracer::send_reference_stats_event(ReferenceType type, size_t count) cons } } +void GCTracer::send_metaspace_chunk_free_list_summary(GCWhen::Type when, Metaspace::MetadataType mdtype, + const MetaspaceChunkFreeListSummary& summary) const { + EventMetaspaceChunkFreeListSummary e; + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.set_when(when); + e.set_metadataType(mdtype); + + e.set_specializedChunks(summary.num_specialized_chunks()); + e.set_specializedChunksTotalSize(summary.specialized_chunks_size_in_bytes()); + + e.set_smallChunks(summary.num_small_chunks()); + e.set_smallChunksTotalSize(summary.small_chunks_size_in_bytes()); + + e.set_mediumChunks(summary.num_medium_chunks()); + e.set_mediumChunksTotalSize(summary.medium_chunks_size_in_bytes()); + + e.set_humongousChunks(summary.num_humongous_chunks()); + e.set_humongousChunksTotalSize(summary.humongous_chunks_size_in_bytes()); + + e.commit(); + } +} + void ParallelOldTracer::send_parallel_old_event() const { EventGCParallelOld e(UNTIMED); if (e.should_commit()) { @@ -246,6 +270,7 @@ void GCTracer::send_meta_space_summary_event(GCWhen::Type when, const MetaspaceS if (e.should_commit()) { e.set_gcId(_shared_gc_info.id()); e.set_when((u1) when); + e.set_gcThreshold(meta_space_summary.capacity_until_GC()); e.set_metaspace(to_trace_struct(meta_space_summary.meta_space())); e.set_dataSpace(to_trace_struct(meta_space_summary.data_space())); e.set_classSpace(to_trace_struct(meta_space_summary.class_space())); diff --git a/src/share/vm/gc_interface/collectedHeap.cpp b/src/share/vm/gc_interface/collectedHeap.cpp index 4efb5651b0377a9769c044acd424f0f41b2c2c37..071ca3812d220435f8cb4daca94df5885875078d 100644 --- a/src/share/vm/gc_interface/collectedHeap.cpp +++ b/src/share/vm/gc_interface/collectedHeap.cpp @@ -97,7 +97,13 @@ MetaspaceSummary CollectedHeap::create_metaspace_summary() { MetaspaceAux::allocated_used_bytes(Metaspace::ClassType), MetaspaceAux::reserved_bytes(Metaspace::ClassType)); - return MetaspaceSummary(meta_space, data_space, class_space); + const MetaspaceChunkFreeListSummary& ms_chunk_free_list_summary = + MetaspaceAux::chunk_free_list_summary(Metaspace::NonClassType); + const MetaspaceChunkFreeListSummary& class_chunk_free_list_summary = + MetaspaceAux::chunk_free_list_summary(Metaspace::ClassType); + + return MetaspaceSummary(MetaspaceGC::capacity_until_GC(), meta_space, data_space, class_space, + ms_chunk_free_list_summary, class_chunk_free_list_summary); } void CollectedHeap::print_heap_before_gc() { @@ -128,8 +134,10 @@ void CollectedHeap::unregister_nmethod(nmethod* nm) { void CollectedHeap::trace_heap(GCWhen::Type when, GCTracer* gc_tracer) { const GCHeapSummary& heap_summary = create_heap_summary(); + gc_tracer->report_gc_heap_summary(when, heap_summary); + const MetaspaceSummary& metaspace_summary = create_metaspace_summary(); - gc_tracer->report_gc_heap_summary(when, heap_summary, metaspace_summary); + gc_tracer->report_metaspace_summary(when, metaspace_summary); } void CollectedHeap::trace_heap_before_gc(GCTracer* gc_tracer) { diff --git a/src/share/vm/memory/metaspace.cpp b/src/share/vm/memory/metaspace.cpp index d780cc5ceef44514072e75fb7dbf61491460be0c..6dcc707923dfc2f1318312f6e339ff9803131d04 100644 --- a/src/share/vm/memory/metaspace.cpp +++ b/src/share/vm/memory/metaspace.cpp @@ -32,7 +32,9 @@ #include "memory/gcLocker.hpp" #include "memory/metachunk.hpp" #include "memory/metaspace.hpp" +#include "memory/metaspaceGCThresholdUpdater.hpp" #include "memory/metaspaceShared.hpp" +#include "memory/metaspaceTracer.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "runtime/atomic.inline.hpp" @@ -57,6 +59,7 @@ size_t const allocation_from_dictionary_limit = 4 * K; MetaWord* last_allocated = 0; size_t Metaspace::_compressed_class_space_size; +const MetaspaceTracer* Metaspace::_tracer = NULL; // Used in declarations in SpaceManager and ChunkManager enum ChunkIndex { @@ -182,6 +185,48 @@ class ChunkManager : public CHeapObj { // Remove from a list by size. Selects list based on size of chunk. Metachunk* free_chunks_get(size_t chunk_word_size); +#define index_bounds_check(index) \ + assert(index == SpecializedIndex || \ + index == SmallIndex || \ + index == MediumIndex || \ + index == HumongousIndex, err_msg("Bad index: %d", (int) index)) + + size_t num_free_chunks(ChunkIndex index) const { + index_bounds_check(index); + + if (index == HumongousIndex) { + return _humongous_dictionary.total_free_blocks(); + } + + ssize_t count = _free_chunks[index].count(); + return count == -1 ? 0 : (size_t) count; + } + + size_t size_free_chunks_in_bytes(ChunkIndex index) const { + index_bounds_check(index); + + size_t word_size = 0; + if (index == HumongousIndex) { + word_size = _humongous_dictionary.total_size(); + } else { + const size_t size_per_chunk_in_words = _free_chunks[index].size(); + word_size = size_per_chunk_in_words * num_free_chunks(index); + } + + return word_size * BytesPerWord; + } + + MetaspaceChunkFreeListSummary chunk_free_list_summary() const { + return MetaspaceChunkFreeListSummary(num_free_chunks(SpecializedIndex), + num_free_chunks(SmallIndex), + num_free_chunks(MediumIndex), + num_free_chunks(HumongousIndex), + size_free_chunks_in_bytes(SpecializedIndex), + size_free_chunks_in_bytes(SmallIndex), + size_free_chunks_in_bytes(MediumIndex), + size_free_chunks_in_bytes(HumongousIndex)); + } + // Debug support void verify(); void slow_verify() { @@ -1436,19 +1481,21 @@ void MetaspaceGC::compute_new_size() { expand_bytes = align_size_up(expand_bytes, Metaspace::commit_alignment()); // Don't expand unless it's significant if (expand_bytes >= MinMetaspaceExpansion) { - MetaspaceGC::inc_capacity_until_GC(expand_bytes); - } - if (PrintGCDetails && Verbose) { - size_t new_capacity_until_GC = capacity_until_GC; - gclog_or_tty->print_cr(" expanding:" - " minimum_desired_capacity: %6.1fKB" - " expand_bytes: %6.1fKB" - " MinMetaspaceExpansion: %6.1fKB" - " new metaspace HWM: %6.1fKB", - minimum_desired_capacity / (double) K, - expand_bytes / (double) K, - MinMetaspaceExpansion / (double) K, - new_capacity_until_GC / (double) K); + size_t new_capacity_until_GC = MetaspaceGC::inc_capacity_until_GC(expand_bytes); + Metaspace::tracer()->report_gc_threshold(capacity_until_GC, + new_capacity_until_GC, + MetaspaceGCThresholdUpdater::ComputeNewSize); + if (PrintGCDetails && Verbose) { + gclog_or_tty->print_cr(" expanding:" + " minimum_desired_capacity: %6.1fKB" + " expand_bytes: %6.1fKB" + " MinMetaspaceExpansion: %6.1fKB" + " new metaspace HWM: %6.1fKB", + minimum_desired_capacity / (double) K, + expand_bytes / (double) K, + MinMetaspaceExpansion / (double) K, + new_capacity_until_GC / (double) K); + } } return; } @@ -1527,7 +1574,10 @@ void MetaspaceGC::compute_new_size() { // Don't shrink unless it's significant if (shrink_bytes >= MinMetaspaceExpansion && ((capacity_until_GC - shrink_bytes) >= MetaspaceSize)) { - MetaspaceGC::dec_capacity_until_GC(shrink_bytes); + size_t new_capacity_until_GC = MetaspaceGC::dec_capacity_until_GC(shrink_bytes); + Metaspace::tracer()->report_gc_threshold(capacity_until_GC, + new_capacity_until_GC, + MetaspaceGCThresholdUpdater::ComputeNewSize); } } @@ -2628,6 +2678,19 @@ size_t MetaspaceAux::free_chunks_total_bytes() { return free_chunks_total_words() * BytesPerWord; } +bool MetaspaceAux::has_chunk_free_list(Metaspace::MetadataType mdtype) { + return Metaspace::get_chunk_manager(mdtype) != NULL; +} + +MetaspaceChunkFreeListSummary MetaspaceAux::chunk_free_list_summary(Metaspace::MetadataType mdtype) { + if (!has_chunk_free_list(mdtype)) { + return MetaspaceChunkFreeListSummary(); + } + + const ChunkManager* cm = Metaspace::get_chunk_manager(mdtype); + return cm->chunk_free_list_summary(); +} + void MetaspaceAux::print_metaspace_change(size_t prev_metadata_used) { gclog_or_tty->print(", [Metaspace:"); if (PrintGCDetails && Verbose) { @@ -3131,6 +3194,7 @@ void Metaspace::global_initialize() { } MetaspaceGC::initialize(); + _tracer = new MetaspaceTracer(); } Metachunk* Metaspace::get_initialization_chunk(MetadataType mdtype, @@ -3219,8 +3283,12 @@ MetaWord* Metaspace::expand_and_allocate(size_t word_size, MetadataType mdtype) assert(delta_bytes > 0, "Must be"); size_t after_inc = MetaspaceGC::inc_capacity_until_GC(delta_bytes); + + // capacity_until_GC might be updated concurrently, must calculate previous value. size_t before_inc = after_inc - delta_bytes; + tracer()->report_gc_threshold(before_inc, after_inc, + MetaspaceGCThresholdUpdater::ExpandAndAllocate); if (PrintGCDetails && Verbose) { gclog_or_tty->print_cr("Increase capacity to GC from " SIZE_FORMAT " to " SIZE_FORMAT, before_inc, after_inc); @@ -3344,6 +3412,8 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, MetaWord* result = loader_data->metaspace_non_null()->allocate(word_size, mdtype); if (result == NULL) { + tracer()->report_metaspace_allocation_failure(loader_data, word_size, type, mdtype); + // Allocation failed. if (is_init_completed()) { // Only start a GC if the bootstrapping has completed. @@ -3355,7 +3425,7 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, } if (result == NULL) { - report_metadata_oome(loader_data, word_size, mdtype, CHECK_NULL); + report_metadata_oome(loader_data, word_size, type, mdtype, CHECK_NULL); } // Zero initialize. @@ -3369,7 +3439,9 @@ size_t Metaspace::class_chunk_size(size_t word_size) { return class_vsm()->calc_chunk_size(word_size); } -void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, MetadataType mdtype, TRAPS) { +void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, MetaspaceObj::Type type, MetadataType mdtype, TRAPS) { + tracer()->report_metadata_oom(loader_data, word_size, type, mdtype); + // If result is still null, we are out of memory. if (Verbose && TraceMetadataChunkAllocation) { gclog_or_tty->print_cr("Metaspace allocation failed for size " @@ -3412,6 +3484,16 @@ void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_s } } +const char* Metaspace::metadata_type_name(Metaspace::MetadataType mdtype) { + switch (mdtype) { + case Metaspace::ClassType: return "Class"; + case Metaspace::NonClassType: return "Metadata"; + default: + assert(false, err_msg("Got bad mdtype: %d", (int) mdtype)); + return NULL; + } +} + void Metaspace::record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size) { assert(DumpSharedSpaces, "sanity"); diff --git a/src/share/vm/memory/metaspace.hpp b/src/share/vm/memory/metaspace.hpp index 96427cb983323fbb457149552cac0b36a9173fae..364f346d4661f25f982da6cffc02225614593463 100644 --- a/src/share/vm/memory/metaspace.hpp +++ b/src/share/vm/memory/metaspace.hpp @@ -26,6 +26,7 @@ #include "memory/allocation.hpp" #include "memory/memRegion.hpp" +#include "memory/metaspaceChunkFreeListSummary.hpp" #include "runtime/virtualspace.hpp" #include "utilities/exceptions.hpp" @@ -60,6 +61,7 @@ class ChunkManager; class ClassLoaderData; class Metablock; class Metachunk; +class MetaspaceTracer; class MetaWord; class Mutex; class outputStream; @@ -148,6 +150,8 @@ class Metaspace : public CHeapObj { static ChunkManager* _chunk_manager_metadata; static ChunkManager* _chunk_manager_class; + static const MetaspaceTracer* _tracer; + public: static VirtualSpaceList* space_list() { return _space_list; } static VirtualSpaceList* class_space_list() { return _class_space_list; } @@ -163,6 +167,8 @@ class Metaspace : public CHeapObj { return mdtype == ClassType ? chunk_manager_class() : chunk_manager_metadata(); } + static const MetaspaceTracer* tracer() { return _tracer; } + private: // This is used by DumpSharedSpaces only, where only _vsm is used. So we will // maintain a single list for now. @@ -233,7 +239,9 @@ class Metaspace : public CHeapObj { static void purge(); static void report_metadata_oome(ClassLoaderData* loader_data, size_t word_size, - MetadataType mdtype, TRAPS); + MetaspaceObj::Type type, MetadataType mdtype, TRAPS); + + static const char* metadata_type_name(Metaspace::MetadataType mdtype); void print_on(outputStream* st) const; // Debugging support @@ -347,6 +355,9 @@ class MetaspaceAux : AllStatic { return min_chunk_size_words() * BytesPerWord; } + static bool has_chunk_free_list(Metaspace::MetadataType mdtype); + static MetaspaceChunkFreeListSummary chunk_free_list_summary(Metaspace::MetadataType mdtype); + // Print change in used metadata. static void print_metaspace_change(size_t prev_metadata_used); static void print_on(outputStream * out); diff --git a/src/share/vm/memory/metaspaceChunkFreeListSummary.hpp b/src/share/vm/memory/metaspaceChunkFreeListSummary.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bc262f6a19d7258b6f1269f0573bb7ba123c80bc --- /dev/null +++ b/src/share/vm/memory/metaspaceChunkFreeListSummary.hpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014, 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP +#define SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP + +#include "memory/allocation.hpp" + +class MetaspaceChunkFreeListSummary VALUE_OBJ_CLASS_SPEC { + size_t _num_specialized_chunks; + size_t _num_small_chunks; + size_t _num_medium_chunks; + size_t _num_humongous_chunks; + + size_t _specialized_chunks_size_in_bytes; + size_t _small_chunks_size_in_bytes; + size_t _medium_chunks_size_in_bytes; + size_t _humongous_chunks_size_in_bytes; + + public: + MetaspaceChunkFreeListSummary() : + _num_specialized_chunks(0), + _num_small_chunks(0), + _num_medium_chunks(0), + _num_humongous_chunks(0), + _specialized_chunks_size_in_bytes(0), + _small_chunks_size_in_bytes(0), + _medium_chunks_size_in_bytes(0), + _humongous_chunks_size_in_bytes(0) + {} + + MetaspaceChunkFreeListSummary(size_t num_specialized_chunks, + size_t num_small_chunks, + size_t num_medium_chunks, + size_t num_humongous_chunks, + size_t specialized_chunks_size_in_bytes, + size_t small_chunks_size_in_bytes, + size_t medium_chunks_size_in_bytes, + size_t humongous_chunks_size_in_bytes) : + _num_specialized_chunks(num_specialized_chunks), + _num_small_chunks(num_small_chunks), + _num_medium_chunks(num_medium_chunks), + _num_humongous_chunks(num_humongous_chunks), + _specialized_chunks_size_in_bytes(specialized_chunks_size_in_bytes), + _small_chunks_size_in_bytes(small_chunks_size_in_bytes), + _medium_chunks_size_in_bytes(medium_chunks_size_in_bytes), + _humongous_chunks_size_in_bytes(humongous_chunks_size_in_bytes) + {} + + size_t num_specialized_chunks() const { + return _num_specialized_chunks; + } + + size_t num_small_chunks() const { + return _num_small_chunks; + } + + size_t num_medium_chunks() const { + return _num_medium_chunks; + } + + size_t num_humongous_chunks() const { + return _num_humongous_chunks; + } + + size_t specialized_chunks_size_in_bytes() const { + return _specialized_chunks_size_in_bytes; + } + + size_t small_chunks_size_in_bytes() const { + return _small_chunks_size_in_bytes; + } + + size_t medium_chunks_size_in_bytes() const { + return _medium_chunks_size_in_bytes; + } + + size_t humongous_chunks_size_in_bytes() const { + return _humongous_chunks_size_in_bytes; + } +}; + +#endif // SHARE_VM_MEMORY_METASPACE_CHUNK_FREE_LIST_SUMMARY_HPP diff --git a/src/share/vm/memory/metaspaceGCThresholdUpdater.hpp b/src/share/vm/memory/metaspaceGCThresholdUpdater.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cbb221dd33b2c0258cec2b6562bf71d68fbd6750 --- /dev/null +++ b/src/share/vm/memory/metaspaceGCThresholdUpdater.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP +#define SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP + +#include "memory/allocation.hpp" +#include "utilities/debug.hpp" + +class MetaspaceGCThresholdUpdater : public AllStatic { + public: + enum Type { + ComputeNewSize, + ExpandAndAllocate, + Last + }; + + static const char* to_string(MetaspaceGCThresholdUpdater::Type updater) { + switch (updater) { + case ComputeNewSize: + return "compute_new_size"; + case ExpandAndAllocate: + return "expand_and_allocate"; + default: + assert(false, err_msg("Got bad updater: %d", (int) updater)); + return NULL; + }; + } +}; + +#endif // SHARE_VM_MEMORY_METASPACE_GC_THRESHOLD_UPDATER_HPP diff --git a/src/share/vm/memory/metaspaceTracer.cpp b/src/share/vm/memory/metaspaceTracer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd4960aab3e70b7168abdf63cf91764fde4fa4b9 --- /dev/null +++ b/src/share/vm/memory/metaspaceTracer.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014, 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "classfile/classLoaderData.hpp" +#include "memory/metaspaceTracer.hpp" +#include "trace/tracing.hpp" +#include "trace/traceBackend.hpp" + +void MetaspaceTracer::report_gc_threshold(size_t old_val, + size_t new_val, + MetaspaceGCThresholdUpdater::Type updater) const { + EventMetaspaceGCThreshold event; + if (event.should_commit()) { + event.set_oldValue(old_val); + event.set_newValue(new_val); + event.set_updater((u1)updater); + event.commit(); + } +} + +void MetaspaceTracer::report_metaspace_allocation_failure(ClassLoaderData *cld, + size_t word_size, + MetaspaceObj::Type objtype, + Metaspace::MetadataType mdtype) const { + send_allocation_failure_event(cld, word_size, objtype, mdtype); +} + +void MetaspaceTracer::report_metadata_oom(ClassLoaderData *cld, + size_t word_size, + MetaspaceObj::Type objtype, + Metaspace::MetadataType mdtype) const { + send_allocation_failure_event(cld, word_size, objtype, mdtype); +} + +template +void MetaspaceTracer::send_allocation_failure_event(ClassLoaderData *cld, + size_t word_size, + MetaspaceObj::Type objtype, + Metaspace::MetadataType mdtype) const { + E event; + if (event.should_commit()) { + if (cld->is_anonymous()) { + event.set_classLoader(NULL); + event.set_anonymousClassLoader(true); + } else { + if (cld->is_the_null_class_loader_data()) { + event.set_classLoader((Klass*) NULL); + } else { + event.set_classLoader(cld->class_loader()->klass()); + } + event.set_anonymousClassLoader(false); + } + + event.set_size(word_size * BytesPerWord); + event.set_metadataType((u1) mdtype); + event.set_metaspaceObjectType((u1) objtype); + event.commit(); + } +} diff --git a/src/share/vm/memory/metaspaceTracer.hpp b/src/share/vm/memory/metaspaceTracer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4ae0138d58178d8d828b441f9986743bbaf4e937 --- /dev/null +++ b/src/share/vm/memory/metaspaceTracer.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_MEMORY_METASPACE_TRACER_HPP +#define SHARE_VM_MEMORY_METASPACE_TRACER_HPP + +#include "memory/allocation.hpp" +#include "memory/metaspace.hpp" +#include "memory/metaspaceGCThresholdUpdater.hpp" + +class ClassLoaderData; + +class MetaspaceTracer : public CHeapObj { + template + void send_allocation_failure_event(ClassLoaderData *cld, + size_t word_size, + MetaspaceObj::Type objtype, + Metaspace::MetadataType mdtype) const; + public: + void report_gc_threshold(size_t old_val, + size_t new_val, + MetaspaceGCThresholdUpdater::Type updater) const; + void report_metaspace_allocation_failure(ClassLoaderData *cld, + size_t word_size, + MetaspaceObj::Type objtype, + Metaspace::MetadataType mdtype) const; + void report_metadata_oom(ClassLoaderData *cld, + size_t word_size, + MetaspaceObj::Type objtype, + Metaspace::MetadataType mdtype) const; + +}; + +#endif // SHARE_VM_MEMORY_METASPACE_TRACER_HPP diff --git a/src/share/vm/trace/trace.xml b/src/share/vm/trace/trace.xml index 75efeea115e1eee25e10064c38fc05ab53deb93d..cd71b64a2d8a38ca74094055e2efb824ec4f2052 100644 --- a/src/share/vm/trace/trace.xml +++ b/src/share/vm/trace/trace.xml @@ -193,11 +193,48 @@ Declares a structure type that can be used in other events. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/share/vm/trace/tracetypes.xml b/src/share/vm/trace/tracetypes.xml index 9305d2fa75ee3c35d1d1babe1a6ea2a25ffbd36e..eb1c708eadb2a977d10b4341cd02b0e6dd36c7ed 100644 --- a/src/share/vm/trace/tracetypes.xml +++ b/src/share/vm/trace/tracetypes.xml @@ -130,11 +130,26 @@ Now we can use the content + data type in declaring event fields. + + + + + + + + + + + + @@ -324,10 +339,22 @@ Now we can use the content + data type in declaring event fields. + + + + + + + + +