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 arena retired a chunk */    \
 59   DEBUG_ONLY(x_atomic(num_chunks_retired))          \
 60                                                     \
 61   /* Number of times an allocation failed */        \
 62   /*  because we hit a limit. */                    \
 63   x_atomic(num_allocs_failed_limit)                 \
 64                                                     \
 65   /* Number of times an arena was born ... */       \
 66   x_atomic(num_arena_births)                        \
 67   /* ... and died. */                               \
 68   x_atomic(num_arena_deaths)                        \
 69                                                     \
 70   /* Number of times VirtualSpaceNode were */       \
 71   /*  born...  */                                   \
 72   x(num_vsnodes_births)                             \
 73   /* ... and died. */                               \
 74   x(num_vsnodes_deaths)                             \
 75                                                     \
 76   /* Number of times we committed space. */         \
 77   x(num_space_committed)                            \
 78   /* Number of times we uncommitted space. */       \
 79   x(num_space_uncommitted)                          \
 80                                                     \
 81   /* Number of times a chunk was returned to the */ \
 82   /*  freelist (external only). */                  \
 83   x(num_chunks_returned_to_freelist)                \
 84   /* Number of times a chunk was taken from */      \
 85   /*  freelist (external only) */                   \
 86   x(num_chunks_taken_from_freelist)                 \
 87                                                     \
 88   /* Number of successful chunk merges */           \
 89   x(num_chunk_merges)                               \
 90   /* Number of chunk splits */                      \
 91   x(num_chunk_splits)                               \
 92   /* Number of chunk in place enlargements */       \
 93   x(num_chunks_enlarged)                            \
 94                                                     \
 95   /* Number of times we read inconsistent stats. */ \
 96   x(num_inconsistent_stats)                         \
 97 
 98 // Note: We use uintx since 32bit platforms lack 64bit atomic add; this increases
 99 //  the possibility of counter overflows but the probability is very low for any counter
100 //  but num_allocs; note that these counters are for human eyes only.
101 #define DEFINE_COUNTER(name)          static uintx _##name;
102 #define DEFINE_ATOMIC_COUNTER(name)   static volatile uintx _##name;
103   ALL_MY_COUNTERS(DEFINE_COUNTER, DEFINE_ATOMIC_COUNTER)
104 #undef DEFINE_COUNTER
105 #undef DEFINE_ATOMIC_COUNTER
106 
107 public:
108 
109 // incrementors
110 #define INCREMENTOR(name)           static void inc_##name() { _##name++; }
111 #define INCREMENTOR_ATOMIC(name)    static void inc_##name() { Atomic::inc(&_##name); }
112   ALL_MY_COUNTERS(INCREMENTOR, INCREMENTOR_ATOMIC)
113 #undef INCREMENTOR
114 #undef INCREMENTOR_ATOMIC
115 
116 // getters
117 #define GETTER(name)                static uint64_t name() { return _##name; }
118   ALL_MY_COUNTERS(GETTER, GETTER)
119 #undef GETTER
120 
121   static void print_on(outputStream* st);
122 
123 };
124 
125 } // namespace metaspace
126 
127 #endif // SHARE_MEMORY_METASPACE_INTERNALSTATS_HPP