1 /*
  2  * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
  3  * Copyright (c) 2020, 2022 SAP SE. All rights reserved.
  4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  5  *
  6  * This code is free software; you can redistribute it and/or modify it
  7  * under the terms of the GNU General Public License version 2 only, as
  8  * published by the Free Software Foundation.
  9  *
 10  * This code is distributed in the hope that it will be useful, but WITHOUT
 11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13  * version 2 for more details (a copy is included in the LICENSE file that
 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  *
 24  */
 25 
 26 #ifndef SHARE_MEMORY_METASPACE_INTERNALSTATS_HPP
 27 #define SHARE_MEMORY_METASPACE_INTERNALSTATS_HPP
 28 
 29 #include "memory/allStatic.hpp"
 30 #include "runtime/atomic.hpp"
 31 #include "utilities/globalDefinitions.hpp"
 32 
 33 class outputStream;
 34 
 35 namespace metaspace {
 36 
 37 // These are some counters useful for debugging and analyzing Metaspace problems.
 38 // They get printed as part of the Metaspace report (e.g. via jcmd VM.metaspace)
 39 
 40 class InternalStats : public AllStatic {
 41 
 42   // Note: all counters which are modified on the classloader local allocation path
 43   //   (not under ExpandLock protection) have to be atomic.
 44 
 45 #define ALL_MY_COUNTERS(x, x_atomic)                \
 46                                                     \
 47   /* Number of allocations. */                      \
 48   DEBUG_ONLY(x_atomic(num_allocs))                  \
 49                                                     \
 50   /* Number of external deallocations */            \
 51   /* (excluding retired chunk remains) */           \
 52   DEBUG_ONLY(x_atomic(num_deallocs))                \
 53                                                     \
 54   /* Number of times an allocation was satisfied */ \
 55   /*  from deallocated blocks. */                   \
 56   DEBUG_ONLY(x_atomic(num_allocs_from_deallocated_blocks)) \
 57                                                     \
 58   /* Number of times an non-class allocation was */ \
 59   /*  satisfied via deallocated blocks from      */ \
 60   /*  class space. */                               \
 61   DEBUG_ONLY(x_atomic(num_allocs_stolen_from_class_space)) \
 62                                                    \
 63   /* Number of splinter blocks added from        */ \
 64   /*  Klass alignment gaps                       */ \
 65   DEBUG_ONLY(x_atomic(num_klass_alignment_splinters_added)) \
 66                                                     \
 67   /* Number of times an arena retired a chunk */    \
 68   DEBUG_ONLY(x_atomic(num_chunks_retired))          \
 69                                                     \
 70   /* Number of times an allocation failed */        \
 71   /*  because we hit a limit. */                    \
 72   x_atomic(num_allocs_failed_limit)                 \
 73                                                     \
 74   /* Number of times an arena was born ... */       \
 75   x_atomic(num_arena_births)                        \
 76   /* ... and died. */                               \
 77   x_atomic(num_arena_deaths)                        \
 78                                                     \
 79   /* Number of times VirtualSpaceNode were */       \
 80   /*  born...  */                                   \
 81   x(num_vsnodes_births)                             \
 82   /* ... and died. */                               \
 83   x(num_vsnodes_deaths)                             \
 84                                                     \
 85   /* Number of times we committed space. */         \
 86   x(num_space_committed)                            \
 87   /* Number of times we uncommitted space. */       \
 88   x(num_space_uncommitted)                          \
 89                                                     \
 90   /* Number of times a chunk was returned to the */ \
 91   /*  freelist (external only). */                  \
 92   x(num_chunks_returned_to_freelist)                \
 93   /* Number of times a chunk was taken from */      \
 94   /*  freelist (external only) */                   \
 95   x(num_chunks_taken_from_freelist)                 \
 96                                                     \
 97   /* Number of successful chunk merges */           \
 98   x(num_chunk_merges)                               \
 99   /* Number of chunk splits */                      \
100   x(num_chunk_splits)                               \
101   /* Number of chunk in place enlargements */       \
102   x(num_chunks_enlarged)                            \
103                                                     \
104   /* Number of times we read inconsistent stats. */ \
105   x(num_inconsistent_stats)                         \
106 
107 // Note: We use uintx since 32bit platforms lack 64bit atomic add; this increases
108 //  the possibility of counter overflows but the probability is very low for any counter
109 //  but num_allocs; note that these counters are for human eyes only.
110 #define DEFINE_COUNTER(name)          static uintx _##name;
111 #define DEFINE_ATOMIC_COUNTER(name)   static volatile uintx _##name;
112   ALL_MY_COUNTERS(DEFINE_COUNTER, DEFINE_ATOMIC_COUNTER)
113 #undef DEFINE_COUNTER
114 #undef DEFINE_ATOMIC_COUNTER
115 
116 public:
117 
118 // incrementors
119 #define INCREMENTOR(name)           static void inc_##name() { _##name++; }
120 #define INCREMENTOR_ATOMIC(name)    static void inc_##name() { Atomic::inc(&_##name); }
121   ALL_MY_COUNTERS(INCREMENTOR, INCREMENTOR_ATOMIC)
122 #undef INCREMENTOR
123 #undef INCREMENTOR_ATOMIC
124 
125 // getters
126 #define GETTER(name)                static uint64_t name() { return _##name; }
127   ALL_MY_COUNTERS(GETTER, GETTER)
128 #undef GETTER
129 
130   static void print_on(outputStream* st);
131 
132 };
133 
134 } // namespace metaspace
135 
136 #endif // SHARE_MEMORY_METASPACE_INTERNALSTATS_HPP