1 /*
2 * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_RUNTIME_PERFDATA_HPP
26 #define SHARE_RUNTIME_PERFDATA_HPP
27
28 #include "memory/allocation.hpp"
29 #include "runtime/atomicAccess.hpp"
30 #include "runtime/perfDataTypes.hpp"
31 #include "runtime/perfMemory.hpp"
32 #include "runtime/timer.hpp"
33
34 template <typename T> class GrowableArray;
35
36 /* jvmstat global and subsystem counter name space - enumeration value
37 * serve as an index into the PerfDataManager::_name_space[] array
38 * containing the corresponding name space string. Only the top level
39 * subsystem name spaces are represented here.
40 */
41 enum CounterNS {
42 // top level name spaces
43 JAVA_NS,
44 COM_NS,
45 SUN_NS,
46 // subsystem name spaces
47 JAVA_GC, // Garbage Collection name spaces
48 COM_GC,
49 SUN_GC,
50 JAVA_CI, // Compiler name spaces
51 COM_CI,
52 SUN_CI,
53 JAVA_CLS, // Class Loader name spaces
54 COM_CLS,
55 SUN_CLS,
56 JAVA_RT, // Runtime name spaces
57 COM_RT,
58 SUN_RT,
59 JAVA_OS, // Operating System name spaces
60 COM_OS,
61 SUN_OS,
62 JAVA_THREADS, // Threads System name spaces
63 COM_THREADS,
64 SUN_THREADS,
65 JAVA_THREADS_CPUTIME, // Thread CPU time name spaces
66 COM_THREADS_CPUTIME,
67 SUN_THREADS_CPUTIME,
68 JAVA_PROPERTY, // Java Property name spaces
69 COM_PROPERTY,
70 SUN_PROPERTY,
71 NULL_NS,
72 COUNTERNS_LAST = NULL_NS
73 };
74
75 /*
76 * Classes to support access to production performance data
77 *
78 * The PerfData class structure is provided for creation, access, and update
79 * of performance data (a.k.a. instrumentation) in a specific memory region
80 * which is possibly accessible as shared memory. Although not explicitly
81 * prevented from doing so, developers should not use the values returned
82 * by accessor methods to make algorithmic decisions as they are potentially
83 * extracted from a shared memory region. Although any shared memory region
84 * created is with appropriate access restrictions, allowing read-write access
85 * only to the principal that created the JVM, it is believed that the
86 * shared memory region facilitates an easier attack path than attacks
87 * launched through mechanisms such as /proc. For this reason, it is
88 * recommended that data returned by PerfData accessor methods be used
89 * cautiously.
90 *
91 * There are three variability classifications of performance data
92 * Constants - value is written to the PerfData memory once, on creation
93 * Variables - value is modifiable, with no particular restrictions
94 * Counters - value is monotonically changing (increasing or decreasing)
95 *
96 * The performance data items can also have various types. The class
97 * hierarchy and the structure of the memory region are designed to
98 * accommodate new types as they are needed. Types are specified in
99 * terms of Java basic types, which accommodates client applications
100 * written in the Java programming language. The class hierarchy is:
101 *
102 * - PerfData (Abstract)
103 * - PerfLong (Abstract)
104 * - PerfLongConstant (alias: PerfConstant)
105 * - PerfLongVariant (Abstract)
106 * - PerfLongVariable (alias: PerfVariable)
107 * - PerfLongCounter (alias: PerfCounter)
108 *
109 * - PerfByteArray (Abstract)
110 * - PerfString (Abstract)
111 * - PerfStringVariable
112 * - PerfStringConstant
113 *
114 *
115 * As seen in the class hierarchy, the initially supported types are:
116 *
117 * Long - performance data holds a Java long type
118 * ByteArray - performance data holds an array of Java bytes
119 * used for holding C++ char arrays.
120 *
121 * The String type is derived from the ByteArray type.
122 *
123 * A PerfData subtype is not required to provide an implementation for
124 * each variability classification. For example, the String type provides
125 * Variable and Constant variability classifications in the PerfStringVariable
126 * and PerfStringConstant classes, but does not provide a counter type.
127 *
128 * Performance data are also described by a unit of measure. Units allow
129 * client applications to make reasonable decisions on how to treat
130 * performance data generically, preventing the need to hard-code the
131 * specifics of a particular data item in client applications. The current
132 * set of units are:
133 *
134 * None - the data has no units of measure
135 * Bytes - data is measured in bytes
136 * Ticks - data is measured in clock ticks
137 * Events - data is measured in events. For example,
138 * the number of garbage collection events or the
139 * number of methods compiled.
140 * String - data is not numerical. For example,
141 * the java command line options
142 * Hertz - data is a frequency
143 *
144 * The performance counters also provide a support attribute, indicating
145 * the stability of the counter as a programmatic interface. The support
146 * level is also implied by the name space in which the counter is created.
147 * The counter name space support conventions follow the Java package, class,
148 * and property support conventions:
149 *
150 * java.* - stable, supported interface
151 * com.sun.* - unstable, supported interface
152 * sun.* - unstable, unsupported interface
153 *
154 * In the above context, unstable is a measure of the interface support
155 * level, not the implementation stability level.
156 *
157 * Currently, instances of PerfData subtypes are considered to have
158 * a life time equal to that of the VM and are managed by the
159 * PerfDataManager class. All constructors for the PerfData class and
160 * its subtypes have protected constructors. Creation of PerfData
161 * instances is performed by invoking various create methods on the
162 * PerfDataManager class. Users should not attempt to delete these
163 * instances as the PerfDataManager class expects to perform deletion
164 * operations on exit of the VM.
165 *
166 * Examples:
167 *
168 * Creating performance counter that holds a monotonically increasing
169 * long data value with units specified in U_Bytes in the "java.gc.*"
170 * name space.
171 *
172 * PerfLongCounter* foo_counter;
173 *
174 * foo_counter = PerfDataManager::create_long_counter(JAVA_GC, "foo",
175 * PerfData::U_Bytes,
176 * optionalInitialValue,
177 * CHECK);
178 * foo_counter->inc();
179 *
180 * Creating a performance counter that holds a variably change long
181 * data value with units specified in U_Bytes in the "com.sun.ci
182 * name space.
183 *
184 * PerfLongVariable* bar_variable;
185 * bar_variable = PerfDataManager::create_long_variable(COM_CI, "bar",
186 .* PerfData::U_Bytes,
187 * optionalInitialValue,
188 * CHECK);
189 *
190 * bar_variable->inc();
191 * bar_variable->set_value(0);
192 *
193 * Creating a performance counter that holds a constant string value in
194 * the "sun.cls.*" name space.
195 *
196 * PerfDataManager::create_string_constant(SUN_CLS, "foo", string, CHECK);
197 *
198 * Although the create_string_constant() factory method returns a pointer
199 * to the PerfStringConstant object, it can safely be ignored. Developers
200 * are not encouraged to access the string constant's value via this
201 * pointer at this time due to security concerns.
202 *
203 * For additional uses of PerfData subtypes, see the utility classes
204 * PerfTraceTime and PerfTraceTimedEvent below.
205 *
206 * Always-on counters can be created independent of
207 * the UsePerfData flag. Counters will be created on the c-heap
208 * if UsePerfData is false.
209 *
210 * Until further notice, all PerfData objects should be created and
211 * manipulated within a guarded block. The guard variable is
212 * UsePerfData, a product flag set to true by default. This flag may
213 * be removed from the product in the future.
214 *
215 * There are possible shutdown races between counter uses and counter
216 * destruction code. Normal shutdown happens with taking VM_Exit safepoint
217 * operation, so in the vast majority of uses this is not an issue. On the
218 * paths where a concurrent access can still happen when VM is at safepoint,
219 * use the following pattern to coordinate with shutdown:
220 *
221 * {
222 * GlobalCounter::CriticalSection cs(Thread::current());
223 * if (PerfDataManager::has_PerfData()) {
224 * <update-counter>
225 * }
226 * }
227 */
228 class PerfData : public CHeapObj<mtInternal> {
229
230 friend class PerfDataManager; // for access to protected destructor
231 friend class VMStructs;
232
233 public:
234
235 // the Variability enum must be kept in synchronization with the
236 // the com.sun.hotspot.perfdata.Variability class
237 enum Variability {
238 V_Constant = 1,
239 V_Monotonic = 2,
240 V_Variable = 3,
241 V_last = V_Variable
242 };
243
244 // the Units enum must be kept in synchronization with the
245 // the com.sun.hotspot.perfdata.Units class
246 enum Units {
247 U_None = 1,
248 U_Bytes = 2,
249 U_Ticks = 3,
250 U_Events = 4,
251 U_String = 5,
252 U_Hertz = 6,
253 U_Last = U_Hertz
254 };
255
256 // Miscellaneous flags
257 enum Flags {
258 F_None = 0x0,
259 F_Supported = 0x1 // interface is supported - java.* and com.sun.*
260 };
261
262 private:
263 char* _name;
264 Variability _v;
265 Units _u;
266 bool _on_c_heap;
267 Flags _flags;
268
269 PerfDataEntry* _pdep;
270
271 protected:
272
273 void *_valuep;
274
275 PerfData(CounterNS ns, const char* name, Units u, Variability v);
276 virtual ~PerfData();
277
278 // create the entry for the PerfData item in the PerfData memory region.
279 // this region is maintained separately from the PerfData objects to
280 // facilitate its use by external processes.
281 void create_entry(BasicType dtype, size_t dsize, size_t dlen = 0);
282
283 public:
284
285 // returns a boolean indicating the validity of this object.
286 // the object is valid if and only if memory in PerfMemory
287 // region was successfully allocated.
288 inline bool is_valid() { return _valuep != nullptr; }
289
290 // returns a boolean indicating whether the underlying object
291 // was allocated in the PerfMemory region or on the C heap.
292 inline bool is_on_c_heap() { return _on_c_heap; }
293
294 // returns a pointer to a char* containing the name of the item.
295 // The pointer returned is the pointer to a copy of the name
296 // passed to the constructor, not the pointer to the name in the
297 // PerfData memory region. This redundancy is maintained for
298 // security reasons as the PerfMemory region may be in shared
299 // memory.
300 const char* name() const { return _name; }
301 bool name_equals(const char* name) const;
302
303 // returns the variability classification associated with this item
304 Variability variability() { return _v; }
305
306 // returns the units associated with this item.
307 Units units() { return _u; }
308
309 // returns the flags associated with this item.
310 Flags flags() { return _flags; }
311
312 // returns the address of the data portion of the item in the
313 // PerfData memory region.
314 inline void* get_address() { return _valuep; }
315 };
316
317 /*
318 * PerfLong is the base class for the various Long PerfData subtypes.
319 * it contains implementation details that are common among its derived
320 * types.
321 */
322 class PerfLong : public PerfData {
323
324 protected:
325
326 PerfLong(CounterNS ns, const char* namep, Units u, Variability v);
327
328 public:
329 // returns the value of the data portion of the item in the
330 // PerfData memory region.
331 inline jlong get_value() { return *(jlong*)_valuep; }
332 };
333
334 /*
335 * The PerfLongConstant class, and its alias PerfConstant, implement
336 * a PerfData subtype that holds a jlong data value that is set upon
337 * creation of an instance of this class. This class provides no
338 * methods for changing the data value stored in PerfData memory region.
339 */
340 class PerfLongConstant : public PerfLong {
341
342 friend class PerfDataManager; // for access to protected constructor
343
344 protected:
345
346 PerfLongConstant(CounterNS ns, const char* namep, Units u,
347 jlong initial_value=0)
348 : PerfLong(ns, namep, u, V_Constant) {
349
350 if (is_valid()) *(jlong*)_valuep = initial_value;
351 }
352 };
353
354 /*
355 * The PerfLongVariant class, and its alias PerfVariant, implement
356 * a PerfData subtype that holds a jlong data value that can be modified
357 * in an unrestricted manner. This class provides the implementation details
358 * for common functionality among its derived types.
359 */
360 class PerfLongVariant : public PerfLong {
361
362 protected:
363 PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
364 jlong initial_value=0)
365 : PerfLong(ns, namep, u, v) {
366 if (is_valid()) *(jlong*)_valuep = initial_value;
367 }
368
369 public:
370 inline void inc() { (*(jlong*)_valuep)++; }
371 inline void inc(jlong val) { (*(jlong*)_valuep) += val; }
372 inline void dec(jlong val) { inc(-val); }
373 inline void reset() { (*(jlong*)_valuep) = 0; }
374 };
375
376 /*
377 * The PerfLongCounter class, and its alias PerfCounter, implement
378 * a PerfData subtype that holds a jlong data value that can (should)
379 * be modified in a monotonic manner. The inc(jlong) and add(jlong)
380 * methods can be passed negative values to implement a monotonically
381 * decreasing value. However, we rely upon the programmer to honor
382 * the notion that this counter always moves in the same direction -
383 * either increasing or decreasing.
384 */
385 class PerfLongCounter : public PerfLongVariant {
386
387 friend class PerfDataManager; // for access to protected constructor
388
389 protected:
390
391 PerfLongCounter(CounterNS ns, const char* namep, Units u,
392 jlong initial_value=0)
393 : PerfLongVariant(ns, namep, u, V_Monotonic,
394 initial_value) { }
395 };
396
397 /*
398 * The PerfLongVariable class, and its alias PerfVariable, implement
399 * a PerfData subtype that holds a jlong data value that can
400 * be modified in an unrestricted manner.
401 */
402 class PerfLongVariable : public PerfLongVariant {
403
404 friend class PerfDataManager; // for access to protected constructor
405
406 protected:
407
408 PerfLongVariable(CounterNS ns, const char* namep, Units u,
409 jlong initial_value=0)
410 : PerfLongVariant(ns, namep, u, V_Variable,
411 initial_value) { }
412
413 public:
414 inline void set_value(jlong val) { (*(jlong*)_valuep) = val; }
415 };
416
417 /*
418 * The PerfByteArray provides a PerfData subtype that allows the creation
419 * of a contiguous region of the PerfData memory region for storing a vector
420 * of bytes. This class is currently intended to be a base class for
421 * the PerfString class, and cannot be instantiated directly.
422 */
423 class PerfByteArray : public PerfData {
424
425 protected:
426 jint _length;
427
428 PerfByteArray(CounterNS ns, const char* namep, Units u, Variability v,
429 jint length);
430 };
431
432 class PerfString : public PerfByteArray {
433
434 protected:
435
436 void set_string(const char* s2);
437
438 PerfString(CounterNS ns, const char* namep, Variability v, jint length,
439 const char* initial_value)
440 : PerfByteArray(ns, namep, U_String, v, length) {
441 if (is_valid()) set_string(initial_value);
442 }
443
444 };
445
446 /*
447 * The PerfStringConstant class provides a PerfData sub class that
448 * allows a null terminated string of single byte characters to be
449 * stored in the PerfData memory region.
450 */
451 class PerfStringConstant : public PerfString {
452
453 friend class PerfDataManager; // for access to protected constructor
454
455 protected:
456
457 // Restrict string constant lengths to be <= PerfMaxStringConstLength.
458 // This prevents long string constants, as can occur with very
459 // long classpaths or java command lines, from consuming too much
460 // PerfData memory.
461 PerfStringConstant(CounterNS ns, const char* namep,
462 const char* initial_value);
463 };
464
465 /*
466 * The PerfStringVariable class provides a PerfData sub class that
467 * allows a null terminated string of single byte character data
468 * to be stored in PerfData memory region. The string value can be reset
469 * after initialization. If the string value is >= max_length, then
470 * it will be truncated to max_length characters. The copied string
471 * is always null terminated.
472 */
473 class PerfStringVariable : public PerfString {
474
475 friend class PerfDataManager; // for access to protected constructor
476
477 protected:
478
479 PerfStringVariable(CounterNS ns, const char* namep, jint max_length,
480 const char* initial_value)
481 : PerfString(ns, namep, V_Variable, max_length+1,
482 initial_value) { }
483
484 public:
485 inline void set_value(const char* val) { set_string(val); }
486 };
487
488
489 /*
490 * The PerfDataList class is a container class for managing lists
491 * of PerfData items. The intention of this class is to allow for
492 * alternative implementations for management of list of PerfData
493 * items without impacting the code that uses the lists.
494 *
495 * The initial implementation is based upon GrowableArray. Searches
496 * on GrowableArray types is linear in nature and this may become
497 * a performance issue for creation of PerfData items, particularly
498 * from Java code where a test for existence is implemented as a
499 * search over all existing PerfData items.
500 *
501 * The abstraction is not complete. A more general container class
502 * would provide an Iterator abstraction that could be used to
503 * traverse the lists. This implementation still relies upon integer
504 * iterators and the at(int index) method. However, the GrowableArray
505 * is not directly visible outside this class and can be replaced by
506 * some other implementation, as long as that implementation provides
507 * a mechanism to iterate over the container by index.
508 */
509 class PerfDataList : public CHeapObj<mtInternal> {
510
511 private:
512
513 // GrowableArray implementation
514 typedef GrowableArray<PerfData*> PerfDataArray;
515
516 PerfDataArray* _set;
517
518 // method to search for a instrumentation object by name
519 static bool by_name(const char* name, PerfData* pd);
520
521 protected:
522 // we expose the implementation here to facilitate the clone
523 // method.
524 PerfDataArray* get_impl() { return _set; }
525
526 public:
527
528 // create a PerfDataList with the given initial length
529 PerfDataList(int length);
530
531 // create a PerfDataList as a shallow copy of the given PerfDataList
532 PerfDataList(PerfDataList* p);
533
534 ~PerfDataList();
535
536 // return the PerfData item indicated by name,
537 // or null if it doesn't exist.
538 PerfData* find_by_name(const char* name);
539
540 // return true if a PerfData item with the name specified in the
541 // argument exists, otherwise return false.
542 bool contains(const char* name) { return find_by_name(name) != nullptr; }
543
544 // return the number of PerfData items in this list
545 inline int length();
546
547 // add a PerfData item to this list
548 inline void append(PerfData *p);
549
550 // create a new PerfDataList from this list. The new list is
551 // a shallow copy of the original list and care should be taken
552 // with respect to delete operations on the elements of the list
553 // as the are likely in use by another copy of the list.
554 PerfDataList* clone();
555
556 // for backward compatibility with GrowableArray - need to implement
557 // some form of iterator to provide a cleaner abstraction for
558 // iteration over the container.
559 inline PerfData* at(int index);
560 };
561
562 class PerfTickCounters : public CHeapObj<mtInternal> {
563 private:
564 const char* _name;
565 PerfCounter* const _elapsed_counter;
566 PerfCounter* const _thread_counter;
567 public:
568 PerfTickCounters(const char* name, PerfCounter* elapsed_counter, PerfCounter* thread_counter) :
569 _name(name), _elapsed_counter(elapsed_counter), _thread_counter(thread_counter) {
570 }
571
572 const char* name() { return _name; }
573
574 PerfCounter* elapsed_counter() const {
575 return _elapsed_counter;
576 }
577 long elapsed_counter_value() const {
578 return _elapsed_counter->get_value();
579 }
580 inline jlong elapsed_counter_value_ms() const;
581 inline jlong elapsed_counter_value_us() const;
582
583 PerfCounter* thread_counter() const {
584 return _thread_counter;
585 }
586 jlong thread_counter_value() const {
587 return _thread_counter->get_value();
588 }
589 inline jlong thread_counter_value_ms() const;
590 inline jlong thread_counter_value_us() const;
591
592 void reset() {
593 _elapsed_counter->reset();
594 _thread_counter->reset();
595 }
596 };
597
598 /*
599 * The PerfDataManager class is responsible for creating PerfData
600 * subtypes via a set a factory methods and for managing lists
601 * of the various PerfData types.
602 */
603 class PerfDataManager : AllStatic {
604 private:
605 static PerfDataList* _all;
606 static PerfDataList* _constants;
607 static const char* _name_spaces[];
608 static volatile bool _has_PerfData;
609
610 // add a PerfData item to the list(s) of know PerfData objects
611 static void add_item(PerfData* p);
612
613 static void create_system_property_instrumentation(TRAPS);
614 static void assert_system_property(const char* name, const char* value, TRAPS);
615 static void add_property_constant(CounterNS name_space, const char* name, const char* value, TRAPS);
616 static void add_property_constant(CounterNS name_space, const char* name, TRAPS);
617 static void add_optional_property_constant(CounterNS name_space, const char* name, TRAPS);
618 public:
619 // Creates miscellaneous perfdata constants
620 static void create_misc_perfdata();
621
622 // method to check for the existence of a PerfData item with
623 // the given name.
624 static inline bool exists(const char* name);
625
626 // method to map a CounterNS enumeration to a namespace string
627 static const char* ns_to_string(CounterNS ns) {
628 return _name_spaces[ns];
629 }
630
631 // methods to test the interface stability of a given counter namespace
632 //
633 static bool is_stable_supported(CounterNS ns) {
634 return (ns != NULL_NS) && ((ns % 3) == JAVA_NS);
635 }
636 static bool is_unstable_supported(CounterNS ns) {
637 return (ns != NULL_NS) && ((ns % 3) == COM_NS);
638 }
639
640 // methods to test the interface stability of a given counter name
641 //
642 static bool is_stable_supported(const char* name) {
643 const char* javadot = "java.";
644 return strncmp(name, javadot, strlen(javadot)) == 0;
645 }
646 static bool is_unstable_supported(const char* name) {
647 const char* comdot = "com.sun.";
648 return strncmp(name, comdot, strlen(comdot)) == 0;
649 }
650
651 // method to construct counter name strings in a given name space.
652 // The string object is allocated from the Resource Area and calls
653 // to this method must be made within a ResourceMark.
654 //
655 static char* counter_name(const char* name_space, const char* name);
656
657 // method to construct name space strings in a given name space.
658 // The string object is allocated from the Resource Area and calls
659 // to this method must be made within a ResourceMark.
660 //
661 static char* name_space(const char* name_space, const char* sub_space) {
662 return counter_name(name_space, sub_space);
663 }
664
665 // same as above, but appends the instance number to the name space
666 //
667 static char* name_space(const char* name_space, const char* sub_space,
668 int instance);
669 static char* name_space(const char* name_space, int instance);
670
671
672 // these methods provide the general interface for creating
673 // performance data resources. The types of performance data
674 // resources can be extended by adding additional create<type>
675 // methods.
676
677 // Constant Types
678 static PerfStringConstant* create_string_constant(CounterNS ns,
679 const char* name,
680 const char *s, TRAPS);
681
682 static PerfLongConstant* create_long_constant(CounterNS ns,
683 const char* name,
684 PerfData::Units u,
685 jlong val, TRAPS);
686
687
688 // Variable Types
689 static PerfStringVariable* create_string_variable(CounterNS ns,
690 const char* name,
691 int max_length,
692 const char *s, TRAPS);
693
694 static PerfLongVariable* create_long_variable(CounterNS ns,
695 const char* name,
696 PerfData::Units u,
697 jlong ival, TRAPS);
698
699 static PerfLongVariable* create_long_variable(CounterNS ns,
700 const char* name,
701 PerfData::Units u, TRAPS) {
702 return create_long_variable(ns, name, u, (jlong)0, THREAD);
703 };
704
705
706 // Counter Types
707 static PerfLongCounter* create_long_counter(CounterNS ns, const char* name,
708 PerfData::Units u,
709 jlong ival, TRAPS);
710
711
712 // these creation methods are provided for ease of use. These allow
713 // Long performance data types to be created with a shorthand syntax.
714
715 static PerfConstant* create_constant(CounterNS ns, const char* name,
716 PerfData::Units u, jlong val, TRAPS) {
717 return create_long_constant(ns, name, u, val, THREAD);
718 }
719
720 static PerfVariable* create_variable(CounterNS ns, const char* name,
721 PerfData::Units u, jlong ival, TRAPS) {
722 return create_long_variable(ns, name, u, ival, THREAD);
723 }
724
725 static PerfVariable* create_variable(CounterNS ns, const char* name,
726 PerfData::Units u, TRAPS) {
727 return create_long_variable(ns, name, u, (jlong)0, THREAD);
728 }
729
730 static PerfCounter* create_counter(CounterNS ns, const char* name,
731 PerfData::Units u, TRAPS) {
732 return create_long_counter(ns, name, u, (jlong)0, THREAD);
733 }
734
735 static PerfTickCounters* create_tick_counters(CounterNS ns,
736 const char* counter_name,
737 const char* elapsed_counter_name,
738 const char* thread_counter_name,
739 PerfData::Units u, TRAPS) {
740 PerfCounter* elapsed_counter = create_long_counter(ns, elapsed_counter_name, u, (jlong)0, THREAD);
741 PerfCounter* thread_counter = create_long_counter(ns, thread_counter_name, u, (jlong)0, THREAD);
742
743 PerfTickCounters* counters = new PerfTickCounters(counter_name, elapsed_counter, thread_counter);
744 return counters;
745 }
746
747 static void destroy();
748 static bool has_PerfData() { return AtomicAccess::load_acquire(&_has_PerfData); }
749 };
750
751 // Useful macros to create the performance counters
752 #define NEWPERFTICKCOUNTER(counter, counter_ns, counter_name) \
753 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
754 PerfData::U_Ticks,CHECK);}
755
756 #define NEWPERFEVENTCOUNTER(counter, counter_ns, counter_name) \
757 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
758 PerfData::U_Events,CHECK);}
759
760 #define NEWPERFBYTECOUNTER(counter, counter_ns, counter_name) \
761 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
762 PerfData::U_Bytes,CHECK);}
763
764 #define NEWPERFTICKCOUNTERS(counter, counter_ns, counter_name) \
765 {counter = PerfDataManager::create_tick_counters(counter_ns, counter_name, counter_name "_elapsed_time", \
766 counter_name "_thread_time", PerfData::U_Ticks,CHECK);}
767
768 // Utility Classes
769
770 /* PerfTraceElapsedTime and PerfTraceThreadTime will administer a PerfCounter used as a time accumulator
771 * for a basic block much like the TraceTime class.
772 * PerfTraceElapsedTime uses elapsedTimer to measure time which reflects the elapsed time,
773 * and PerfTraceThreadTime uses ThreadTimer which reflects thread cpu time.
774 *
775 * Example:
776 *
777 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, 0LL, CHECK);
778 *
779 * {
780 * PerfTraceElapsedTime ptt(my_time_counter);
781 * // perform the operation you want to measure
782 * }
783 *
784 * Note: use of this class does not need to occur within a guarded
785 * block. The UsePerfData guard is used with the implementation
786 * of this class.
787 */
788
789 class PerfTraceTimeBase : public StackObj {
790 friend class PerfPauseTimer;
791 private:
792 BaseTimer* _t;
793 protected:
794 PerfLongCounter* _counter;
795
796 public:
797 inline PerfTraceTimeBase(BaseTimer* t, PerfLongCounter* counter) : _t(t), _counter(counter) {}
798
799 ~PerfTraceTimeBase();
800
801 jlong active_ticks() { return _t->active_ticks(); }
802
803 const char* name() { return _counter->name(); }
804 BaseTimer* timer() { return _t; }
805 };
806
807 class PerfTraceElapsedTime: public PerfTraceTimeBase {
808 protected:
809 elapsedTimer _t;
810
811 public:
812 inline PerfTraceElapsedTime(PerfCounter* counter) : PerfTraceTimeBase(&_t, counter) {
813 if (!UsePerfData || counter == nullptr) { return; }
814 _t.start();
815 }
816 };
817
818 class PerfTraceThreadTime: public PerfTraceTimeBase {
819 protected:
820 ThreadTimer _t;
821
822 public:
823 inline PerfTraceThreadTime(PerfCounter* counter) : PerfTraceTimeBase(&_t, counter) {
824 if (!UsePerfData || !TraceThreadTime || counter == nullptr) { return; }
825 _t.start();
826 }
827 };
828
829 // PerfTraceTime is a utility class to provide the ability to measure both elapsed and thread cpu time using a single object.
830 class PerfTraceTime : public StackObj {
831 friend class PerfPauseTimer;
832 private:
833 PerfTickCounters* _counters;
834 PerfTraceElapsedTime _elapsed_timer;
835 PerfTraceThreadTime _thread_timer;
836
837 public:
838 inline PerfTraceTime(PerfTickCounters* counters, bool is_on = true):
839 _counters(counters),
840 _elapsed_timer(counters != nullptr ? counters->elapsed_counter() : nullptr),
841 _thread_timer(counters != nullptr ? counters->thread_counter() : nullptr) {}
842
843 const char* name() { return _counters->name(); }
844 PerfTraceTimeBase* elapsed_timer() { return &_elapsed_timer; }
845 PerfTraceTimeBase* thread_timer() { return &_thread_timer; }
846
847 jlong elapsed_timer_active_ticks() {
848 return _elapsed_timer.active_ticks();
849 }
850
851 jlong thread_timer_active_ticks() {
852 return _thread_timer.active_ticks();
853 }
854 };
855
856 class PerfPauseTimerBase : public StackObj {
857 protected:
858 bool _is_active;
859 BaseTimer* _timer;
860
861 public:
862 inline PerfPauseTimerBase(PerfTraceTimeBase* timer, bool is_on) : _is_active(false), _timer(nullptr) {
863 _is_active = (is_on && timer != nullptr);
864 if (UsePerfData && _is_active) {
865 _timer = timer->timer();
866 _timer->stop(); // pause
867 }
868 }
869
870 inline ~PerfPauseTimerBase() {
871 if (UsePerfData && _is_active) {
872 assert(_timer != nullptr, "");
873 _timer->start(); // resume
874 }
875 }
876 };
877
878 class PerfPauseTimer : public StackObj {
879 private:
880 PerfPauseTimerBase _elapsed_timer_pause;
881 PerfPauseTimerBase _thread_timer_pause;
882
883 public:
884 inline PerfPauseTimer(PerfTraceTime* timer, bool is_on) :
885 _elapsed_timer_pause(timer != nullptr ? timer->elapsed_timer() : nullptr, is_on),
886 _thread_timer_pause(timer != nullptr ? timer->thread_timer() : nullptr, is_on) {}
887 };
888
889 /* The PerfTraceElapsedTimeEvent class is responsible for counting the
890 * occurrence of some event and measuring the elapsed time of
891 * the event in two separate PerfCounter instances.
892 *
893 * Example:
894 *
895 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, CHECK);
896 * static PerfCounter* my_event_counter = PerfDataManager::create_counter("my.event.counter", PerfData::U_Events, CHECK);
897 *
898 * {
899 * PerfTraceElapsedTimeEvent ptte(my_time_counter, my_event_counter);
900 * // perform the operation you want to count and measure
901 * }
902 *
903 * Note: use of this class does not need to occur within a guarded
904 * block. The UsePerfData guard is used with the implementation
905 * of this class.
906 *
907 * Similarly, PerfTraceThreadTimeEvent can count the occurrence of some event and measure the thread cpu time of the event.
908 * PerfTraceTimedEvent can count the occurrence of some event and measure both the elapsed time and the thread cpu time of the event.
909 */
910 class PerfTraceElapsedTimeEvent: public PerfTraceElapsedTime {
911 protected:
912 PerfLongCounter* _eventp;
913
914 public:
915 inline PerfTraceElapsedTimeEvent(PerfCounter* counter, PerfLongCounter* eventp) : PerfTraceElapsedTime(counter), _eventp(eventp) {
916 if (!UsePerfData || counter == nullptr) return;
917 _eventp->inc();
918 }
919 };
920
921 class PerfTraceThreadTimeEvent: public PerfTraceThreadTime {
922 protected:
923 PerfLongCounter* _eventp;
924
925 public:
926 inline PerfTraceThreadTimeEvent(PerfCounter* counter, PerfLongCounter* eventp) : PerfTraceThreadTime(counter), _eventp(eventp) {
927 if (!UsePerfData || counter == nullptr) return;
928 _eventp->inc();
929 }
930 };
931
932 class PerfTraceTimedEvent : public PerfTraceTime {
933 protected:
934 PerfLongCounter* _eventp;
935
936 public:
937 inline PerfTraceTimedEvent(PerfTickCounters* counters, PerfLongCounter* eventp, bool is_on = true) : PerfTraceTime(counters, is_on), _eventp(eventp) {
938 if (!UsePerfData || !is_on || counters == nullptr) return;
939 _eventp->inc();
940 }
941 };
942 #endif // SHARE_RUNTIME_PERFDATA_HPP