1 /*
2 * Copyright (c) 2001, 2023, 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 *
400 class PerfLongVariant : public PerfLong {
401
402 protected:
403 PerfLongSampleHelper* _sample_helper;
404
405 PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
406 jlong initial_value=0)
407 : PerfLong(ns, namep, u, v) {
408 if (is_valid()) *(jlong*)_valuep = initial_value;
409 }
410
411 PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
412 PerfLongSampleHelper* sample_helper);
413
414 void sample();
415
416 public:
417 inline void inc() { (*(jlong*)_valuep)++; }
418 inline void inc(jlong val) { (*(jlong*)_valuep) += val; }
419 inline void dec(jlong val) { inc(-val); }
420 };
421
422 /*
423 * The PerfLongCounter class, and its alias PerfCounter, implement
424 * a PerfData subtype that holds a jlong data value that can (should)
425 * be modified in a monotonic manner. The inc(jlong) and add(jlong)
426 * methods can be passed negative values to implement a monotonically
427 * decreasing value. However, we rely upon the programmer to honor
428 * the notion that this counter always moves in the same direction -
429 * either increasing or decreasing.
430 */
431 class PerfLongCounter : public PerfLongVariant {
432
433 friend class PerfDataManager; // for access to protected constructor
434
435 protected:
436
437 PerfLongCounter(CounterNS ns, const char* namep, Units u,
438 jlong initial_value=0)
439 : PerfLongVariant(ns, namep, u, V_Monotonic,
606 bool contains(const char* name) { return find_by_name(name) != nullptr; }
607
608 // return the number of PerfData items in this list
609 inline int length();
610
611 // add a PerfData item to this list
612 inline void append(PerfData *p);
613
614 // create a new PerfDataList from this list. The new list is
615 // a shallow copy of the original list and care should be taken
616 // with respect to delete operations on the elements of the list
617 // as the are likely in use by another copy of the list.
618 PerfDataList* clone();
619
620 // for backward compatibility with GrowableArray - need to implement
621 // some form of iterator to provide a cleaner abstraction for
622 // iteration over the container.
623 inline PerfData* at(int index);
624 };
625
626
627 /*
628 * The PerfDataManager class is responsible for creating PerfData
629 * subtypes via a set a factory methods and for managing lists
630 * of the various PerfData types.
631 */
632 class PerfDataManager : AllStatic {
633
634 friend class StatSampler; // for access to protected PerfDataList methods
635
636 private:
637 static PerfDataList* _all;
638 static PerfDataList* _sampled;
639 static PerfDataList* _constants;
640 static const char* _name_spaces[];
641 static volatile bool _has_PerfData;
642
643 // add a PerfData item to the list(s) of know PerfData objects
644 static void add_item(PerfData* p, bool sampled);
645
770 return create_long_variable(ns, name, u, (jlong)0, THREAD);
771 }
772
773 static PerfVariable* create_variable(CounterNS ns, const char* name,
774 PerfData::Units u,
775 PerfSampleHelper* sh, TRAPS) {
776 return create_long_variable(ns, name, u, sh, THREAD);
777 }
778
779 static PerfCounter* create_counter(CounterNS ns, const char* name,
780 PerfData::Units u, TRAPS) {
781 return create_long_counter(ns, name, u, (jlong)0, THREAD);
782 }
783
784 static PerfCounter* create_counter(CounterNS ns, const char* name,
785 PerfData::Units u,
786 PerfSampleHelper* sh, TRAPS) {
787 return create_long_counter(ns, name, u, sh, THREAD);
788 }
789
790 static void destroy();
791 static bool has_PerfData() { return _has_PerfData; }
792 };
793
794 // Useful macros to create the performance counters
795 #define NEWPERFTICKCOUNTER(counter, counter_ns, counter_name) \
796 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
797 PerfData::U_Ticks,CHECK);}
798
799 #define NEWPERFEVENTCOUNTER(counter, counter_ns, counter_name) \
800 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
801 PerfData::U_Events,CHECK);}
802
803 #define NEWPERFBYTECOUNTER(counter, counter_ns, counter_name) \
804 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
805 PerfData::U_Bytes,CHECK);}
806
807 // Utility Classes
808
809 /*
810 * this class will administer a PerfCounter used as a time accumulator
811 * for a basic block much like the TraceTime class.
812 *
813 * Example:
814 *
815 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, 0LL, CHECK);
816 *
817 * {
818 * PerfTraceTime ptt(my_time_counter);
819 * // perform the operation you want to measure
820 * }
821 *
822 * Note: use of this class does not need to occur within a guarded
823 * block. The UsePerfData guard is used with the implementation
824 * of this class.
825 */
826 class PerfTraceTime : public StackObj {
827
828 protected:
829 elapsedTimer _t;
830 PerfLongCounter* _timerp;
831
832 public:
833 inline PerfTraceTime(PerfLongCounter* timerp) : _timerp(timerp) {
834 if (!UsePerfData) return;
835 _t.start();
836 }
837
838 ~PerfTraceTime();
839 };
840
841 /* The PerfTraceTimedEvent class is responsible for counting the
842 * occurrence of some event and measuring the elapsed time of
843 * the event in two separate PerfCounter instances.
844 *
845 * Example:
846 *
847 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, CHECK);
848 * static PerfCounter* my_event_counter = PerfDataManager::create_counter("my.event.counter", PerfData::U_Events, CHECK);
849 *
850 * {
851 * PerfTraceTimedEvent ptte(my_time_counter, my_event_counter);
852 * // perform the operation you want to count and measure
853 * }
854 *
855 * Note: use of this class does not need to occur within a guarded
856 * block. The UsePerfData guard is used with the implementation
857 * of this class.
858 *
859 */
860 class PerfTraceTimedEvent : public PerfTraceTime {
861
862 protected:
863 PerfLongCounter* _eventp;
864
865 public:
866 inline PerfTraceTimedEvent(PerfLongCounter* timerp, PerfLongCounter* eventp): PerfTraceTime(timerp), _eventp(eventp) {
867 if (!UsePerfData) return;
868 _eventp->inc();
869 }
870
871 };
872
873 #endif // SHARE_RUNTIME_PERFDATA_HPP
|
1 /*
2 * Copyright (c) 2001, 2024, 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 *
400 class PerfLongVariant : public PerfLong {
401
402 protected:
403 PerfLongSampleHelper* _sample_helper;
404
405 PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
406 jlong initial_value=0)
407 : PerfLong(ns, namep, u, v) {
408 if (is_valid()) *(jlong*)_valuep = initial_value;
409 }
410
411 PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v,
412 PerfLongSampleHelper* sample_helper);
413
414 void sample();
415
416 public:
417 inline void inc() { (*(jlong*)_valuep)++; }
418 inline void inc(jlong val) { (*(jlong*)_valuep) += val; }
419 inline void dec(jlong val) { inc(-val); }
420 inline void reset() { (*(jlong*)_valuep) = 0; }
421 };
422
423 /*
424 * The PerfLongCounter class, and its alias PerfCounter, implement
425 * a PerfData subtype that holds a jlong data value that can (should)
426 * be modified in a monotonic manner. The inc(jlong) and add(jlong)
427 * methods can be passed negative values to implement a monotonically
428 * decreasing value. However, we rely upon the programmer to honor
429 * the notion that this counter always moves in the same direction -
430 * either increasing or decreasing.
431 */
432 class PerfLongCounter : public PerfLongVariant {
433
434 friend class PerfDataManager; // for access to protected constructor
435
436 protected:
437
438 PerfLongCounter(CounterNS ns, const char* namep, Units u,
439 jlong initial_value=0)
440 : PerfLongVariant(ns, namep, u, V_Monotonic,
607 bool contains(const char* name) { return find_by_name(name) != nullptr; }
608
609 // return the number of PerfData items in this list
610 inline int length();
611
612 // add a PerfData item to this list
613 inline void append(PerfData *p);
614
615 // create a new PerfDataList from this list. The new list is
616 // a shallow copy of the original list and care should be taken
617 // with respect to delete operations on the elements of the list
618 // as the are likely in use by another copy of the list.
619 PerfDataList* clone();
620
621 // for backward compatibility with GrowableArray - need to implement
622 // some form of iterator to provide a cleaner abstraction for
623 // iteration over the container.
624 inline PerfData* at(int index);
625 };
626
627 class PerfTickCounters : public CHeapObj<mtInternal> {
628 private:
629 const char* _name;
630 PerfCounter* const _elapsed_counter;
631 PerfCounter* const _thread_counter;
632 public:
633 PerfTickCounters(const char* name, PerfCounter* elapsed_counter, PerfCounter* thread_counter) :
634 _name(name), _elapsed_counter(elapsed_counter), _thread_counter(thread_counter) {
635 }
636
637 const char* name() { return _name; }
638
639 PerfCounter* elapsed_counter() const {
640 return _elapsed_counter;
641 }
642 long elapsed_counter_value() const {
643 return _elapsed_counter->get_value();
644 }
645 inline long elapsed_counter_value_ms() const;
646
647 PerfCounter* thread_counter() const {
648 return _thread_counter;
649 }
650 long thread_counter_value() const {
651 return _thread_counter->get_value();
652 }
653 inline long thread_counter_value_ms() const;
654
655 void reset() {
656 _elapsed_counter->reset();
657 _thread_counter->reset();
658 }
659 };
660
661 /*
662 * The PerfDataManager class is responsible for creating PerfData
663 * subtypes via a set a factory methods and for managing lists
664 * of the various PerfData types.
665 */
666 class PerfDataManager : AllStatic {
667
668 friend class StatSampler; // for access to protected PerfDataList methods
669
670 private:
671 static PerfDataList* _all;
672 static PerfDataList* _sampled;
673 static PerfDataList* _constants;
674 static const char* _name_spaces[];
675 static volatile bool _has_PerfData;
676
677 // add a PerfData item to the list(s) of know PerfData objects
678 static void add_item(PerfData* p, bool sampled);
679
804 return create_long_variable(ns, name, u, (jlong)0, THREAD);
805 }
806
807 static PerfVariable* create_variable(CounterNS ns, const char* name,
808 PerfData::Units u,
809 PerfSampleHelper* sh, TRAPS) {
810 return create_long_variable(ns, name, u, sh, THREAD);
811 }
812
813 static PerfCounter* create_counter(CounterNS ns, const char* name,
814 PerfData::Units u, TRAPS) {
815 return create_long_counter(ns, name, u, (jlong)0, THREAD);
816 }
817
818 static PerfCounter* create_counter(CounterNS ns, const char* name,
819 PerfData::Units u,
820 PerfSampleHelper* sh, TRAPS) {
821 return create_long_counter(ns, name, u, sh, THREAD);
822 }
823
824 static PerfTickCounters* create_tick_counters(CounterNS ns,
825 const char* counter_name,
826 const char* elapsed_counter_name,
827 const char* thread_counter_name,
828 PerfData::Units u, TRAPS) {
829 PerfCounter* elapsed_counter = create_long_counter(ns, elapsed_counter_name, u, (jlong)0, THREAD);
830 PerfCounter* thread_counter = create_long_counter(ns, thread_counter_name, u, (jlong)0, THREAD);
831
832 PerfTickCounters* counters = new PerfTickCounters(counter_name, elapsed_counter, thread_counter);
833 return counters;
834 }
835
836 static void destroy();
837 static bool has_PerfData() { return _has_PerfData; }
838 };
839
840 // Useful macros to create the performance counters
841 #define NEWPERFTICKCOUNTER(counter, counter_ns, counter_name) \
842 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
843 PerfData::U_Ticks,CHECK);}
844
845 #define NEWPERFEVENTCOUNTER(counter, counter_ns, counter_name) \
846 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
847 PerfData::U_Events,CHECK);}
848
849 #define NEWPERFBYTECOUNTER(counter, counter_ns, counter_name) \
850 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
851 PerfData::U_Bytes,CHECK);}
852
853 #define NEWPERFTICKCOUNTERS(counter, counter_ns, counter_name) \
854 {counter = PerfDataManager::create_tick_counters(counter_ns, counter_name, counter_name "_elapsed_time", \
855 counter_name "_thread_time", PerfData::U_Ticks,CHECK);}
856
857 // Utility Classes
858
859 /* PerfTraceElapsedTime and PerfTraceThreadTime will administer a PerfCounter used as a time accumulator
860 * for a basic block much like the TraceTime class.
861 * PerfTraceElapsedTime uses elapsedTimer to measure time which reflects the elapsed time,
862 * and PerfTraceThreadTime uses ThreadTimer which reflects thread cpu time.
863 *
864 * Example:
865 *
866 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, 0LL, CHECK);
867 *
868 * {
869 * PerfTraceElapsedTime ptt(my_time_counter);
870 * // perform the operation you want to measure
871 * }
872 *
873 * Note: use of this class does not need to occur within a guarded
874 * block. The UsePerfData guard is used with the implementation
875 * of this class.
876 */
877
878 class PerfTraceTimeBase : public StackObj {
879 friend class PerfPauseTimer;
880 private:
881 BaseTimer* _t;
882 protected:
883 PerfLongCounter* _counter;
884
885 public:
886 inline PerfTraceTimeBase(BaseTimer* t, PerfLongCounter* counter, bool is_on) : _t(t), _counter(counter) {}
887
888 ~PerfTraceTimeBase();
889
890 jlong active_ticks() { return _t->active_ticks(); }
891
892 const char* name() { return _counter->name(); }
893 BaseTimer* timer() { return _t; }
894 };
895
896 class PerfTraceElapsedTime: public PerfTraceTimeBase {
897 protected:
898 elapsedTimer _t;
899
900 public:
901 inline PerfTraceElapsedTime(PerfCounter* counter, bool is_on = true) : PerfTraceTimeBase(&_t, counter, is_on) {
902 if (!UsePerfData || !is_on) return;
903 if (counter != nullptr) {
904 _t.start();
905 }
906 }
907 };
908
909 class PerfTraceThreadTime: public PerfTraceTimeBase {
910 protected:
911 ThreadTimer _t;
912
913 public:
914 inline PerfTraceThreadTime(PerfCounter* counter, bool is_on = true) : PerfTraceTimeBase(&_t, counter, is_on) {
915 if (!UsePerfData || !is_on || !TraceThreadTime) return;
916 if (counter != nullptr) {
917 _t.start();
918 }
919 }
920 };
921
922 // PerfTraceTime is a utility class to provide the ability to measure both elapsed and thread cpu time using a single object.
923 class PerfTraceTime : public StackObj {
924 friend class PerfPauseTimer;
925 private:
926 PerfTickCounters* _counters;
927 PerfTraceElapsedTime _elapsed_timer;
928 PerfTraceThreadTime _thread_timer;
929
930 public:
931 inline PerfTraceTime(PerfTickCounters* counters, bool is_on = true):
932 _counters(counters),
933 _elapsed_timer(counters != nullptr ? counters->elapsed_counter() : nullptr, is_on),
934 _thread_timer(counters != nullptr ? counters->thread_counter() : nullptr, is_on) {}
935
936 const char* name() { return _counters->name(); }
937 PerfTraceTimeBase* elapsed_timer() { return &_elapsed_timer; }
938 PerfTraceTimeBase* thread_timer() { return &_thread_timer; }
939
940 jlong elapsed_timer_active_ticks() {
941 return _elapsed_timer.active_ticks();
942 }
943
944 jlong thread_timer_active_ticks() {
945 return _thread_timer.active_ticks();
946 }
947 };
948
949 class PerfPauseTimerBase : public StackObj {
950 protected:
951 bool _is_active;
952 BaseTimer* _timer;
953
954 public:
955 inline PerfPauseTimerBase(PerfTraceTimeBase* timer, bool is_on) : _is_active(false), _timer(nullptr) {
956 _is_active = (is_on && timer != nullptr);
957 if (UsePerfData && _is_active) {
958 _timer = timer->timer();
959 _timer->stop(); // pause
960 }
961 }
962
963 inline ~PerfPauseTimerBase() {
964 if (UsePerfData && _is_active) {
965 assert(_timer != nullptr, "");
966 _timer->start(); // resume
967 }
968 }
969 };
970
971 class PerfPauseTimer : public StackObj {
972 private:
973 PerfPauseTimerBase _elapsed_timer_pause;
974 PerfPauseTimerBase _thread_timer_pause;
975
976 public:
977 inline PerfPauseTimer(PerfTraceTime* timer, bool is_on) :
978 _elapsed_timer_pause(timer != nullptr ? timer->elapsed_timer() : nullptr, is_on),
979 _thread_timer_pause(timer != nullptr ? timer->thread_timer() : nullptr, is_on) {}
980 };
981
982 /* The PerfTraceElapsedTimeEvent class is responsible for counting the
983 * occurrence of some event and measuring the elapsed time of
984 * the event in two separate PerfCounter instances.
985 *
986 * Example:
987 *
988 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, CHECK);
989 * static PerfCounter* my_event_counter = PerfDataManager::create_counter("my.event.counter", PerfData::U_Events, CHECK);
990 *
991 * {
992 * PerfTraceElapsedTimeEvent ptte(my_time_counter, my_event_counter);
993 * // perform the operation you want to count and measure
994 * }
995 *
996 * Note: use of this class does not need to occur within a guarded
997 * block. The UsePerfData guard is used with the implementation
998 * of this class.
999 *
1000 * Similarly, PerfTraceThreadTimeEvent can count the occurrence of some event and measure the thread cpu time of the event.
1001 * PerfTraceTimedEvent can count the occurrence of some event and measure both the elapsed time and the thread cpu time of the event.
1002 */
1003 class PerfTraceElapsedTimeEvent: public PerfTraceElapsedTime {
1004 protected:
1005 PerfLongCounter* _eventp;
1006
1007 public:
1008 inline PerfTraceElapsedTimeEvent(PerfCounter* counter, PerfLongCounter* eventp, bool is_on = true) : PerfTraceElapsedTime(counter, is_on), _eventp(eventp) {
1009 if (!UsePerfData || !is_on) return;
1010 _eventp->inc();
1011 }
1012 };
1013
1014 class PerfTraceThreadTimeEvent: public PerfTraceThreadTime {
1015 protected:
1016 PerfLongCounter* _eventp;
1017
1018 public:
1019 inline PerfTraceThreadTimeEvent(PerfCounter* counter, PerfLongCounter* eventp, bool is_on = true) : PerfTraceThreadTime(counter, is_on), _eventp(eventp) {
1020 if (!UsePerfData || !is_on) return;
1021 _eventp->inc();
1022 }
1023 };
1024
1025 class PerfTraceTimedEvent : public PerfTraceTime {
1026 protected:
1027 PerfLongCounter* _eventp;
1028
1029 public:
1030 inline PerfTraceTimedEvent(PerfTickCounters* counters, PerfLongCounter* eventp, bool is_on = true) : PerfTraceTime(counters, is_on), _eventp(eventp) {
1031 if (!UsePerfData || !is_on) return;
1032 _eventp->inc();
1033 }
1034 };
1035 #endif // SHARE_RUNTIME_PERFDATA_HPP
|