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 || timerp == nullptr) { return; }
835 _t.start();
836 }
837
838 const char* name() const {
839 assert(_timerp != nullptr, "sanity");
840 return _timerp->name();
841 }
842
843 ~PerfTraceTime() {
844 if (!UsePerfData || !_t.is_active()) { return; }
845 _t.stop();
846 _timerp->inc(_t.ticks());
847 }
848 };
849
850 /* The PerfTraceTimedEvent class is responsible for counting the
851 * occurrence of some event and measuring the elapsed time of
852 * the event in two separate PerfCounter instances.
853 *
854 * Example:
855 *
856 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, CHECK);
857 * static PerfCounter* my_event_counter = PerfDataManager::create_counter("my.event.counter", PerfData::U_Events, CHECK);
858 *
859 * {
860 * PerfTraceTimedEvent ptte(my_time_counter, my_event_counter);
861 * // perform the operation you want to count and measure
862 * }
863 *
864 * Note: use of this class does not need to occur within a guarded
865 * block. The UsePerfData guard is used with the implementation
866 * of this class.
867 *
868 */
869 class PerfTraceTimedEvent : public PerfTraceTime {
870
871 protected:
872 PerfLongCounter* _eventp;
873
874 public:
875 inline PerfTraceTimedEvent(PerfLongCounter* timerp, PerfLongCounter* eventp): PerfTraceTime(timerp), _eventp(eventp) {
876 if (!UsePerfData || timerp == nullptr) { return; }
877 _eventp->inc();
878 }
879
880 };
881
882 #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) : _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) : PerfTraceTimeBase(&_t, counter) {
902 if (!UsePerfData || counter == nullptr) { return; }
903 _t.start();
904 }
905 };
906
907 class PerfTraceThreadTime: public PerfTraceTimeBase {
908 protected:
909 ThreadTimer _t;
910
911 public:
912 inline PerfTraceThreadTime(PerfCounter* counter) : PerfTraceTimeBase(&_t, counter) {
913 if (!UsePerfData || !TraceThreadTime || counter == nullptr) { return; }
914 _t.start();
915 }
916 };
917
918 // PerfTraceTime is a utility class to provide the ability to measure both elapsed and thread cpu time using a single object.
919 class PerfTraceTime : public StackObj {
920 friend class PerfPauseTimer;
921 private:
922 PerfTickCounters* _counters;
923 PerfTraceElapsedTime _elapsed_timer;
924 PerfTraceThreadTime _thread_timer;
925
926 public:
927 inline PerfTraceTime(PerfTickCounters* counters, bool is_on = true):
928 _counters(counters),
929 _elapsed_timer(counters != nullptr ? counters->elapsed_counter() : nullptr),
930 _thread_timer(counters != nullptr ? counters->thread_counter() : nullptr) {}
931
932 const char* name() { return _counters->name(); }
933 PerfTraceTimeBase* elapsed_timer() { return &_elapsed_timer; }
934 PerfTraceTimeBase* thread_timer() { return &_thread_timer; }
935
936 jlong elapsed_timer_active_ticks() {
937 return _elapsed_timer.active_ticks();
938 }
939
940 jlong thread_timer_active_ticks() {
941 return _thread_timer.active_ticks();
942 }
943 };
944
945 class PerfPauseTimerBase : public StackObj {
946 protected:
947 bool _is_active;
948 BaseTimer* _timer;
949
950 public:
951 inline PerfPauseTimerBase(PerfTraceTimeBase* timer, bool is_on) : _is_active(false), _timer(nullptr) {
952 _is_active = (is_on && timer != nullptr);
953 if (UsePerfData && _is_active) {
954 _timer = timer->timer();
955 _timer->stop(); // pause
956 }
957 }
958
959 inline ~PerfPauseTimerBase() {
960 if (UsePerfData && _is_active) {
961 assert(_timer != nullptr, "");
962 _timer->start(); // resume
963 }
964 }
965 };
966
967 class PerfPauseTimer : public StackObj {
968 private:
969 PerfPauseTimerBase _elapsed_timer_pause;
970 PerfPauseTimerBase _thread_timer_pause;
971
972 public:
973 inline PerfPauseTimer(PerfTraceTime* timer, bool is_on) :
974 _elapsed_timer_pause(timer != nullptr ? timer->elapsed_timer() : nullptr, is_on),
975 _thread_timer_pause(timer != nullptr ? timer->thread_timer() : nullptr, is_on) {}
976 };
977
978 /* The PerfTraceElapsedTimeEvent class is responsible for counting the
979 * occurrence of some event and measuring the elapsed time of
980 * the event in two separate PerfCounter instances.
981 *
982 * Example:
983 *
984 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, CHECK);
985 * static PerfCounter* my_event_counter = PerfDataManager::create_counter("my.event.counter", PerfData::U_Events, CHECK);
986 *
987 * {
988 * PerfTraceElapsedTimeEvent ptte(my_time_counter, my_event_counter);
989 * // perform the operation you want to count and measure
990 * }
991 *
992 * Note: use of this class does not need to occur within a guarded
993 * block. The UsePerfData guard is used with the implementation
994 * of this class.
995 *
996 * Similarly, PerfTraceThreadTimeEvent can count the occurrence of some event and measure the thread cpu time of the event.
997 * PerfTraceTimedEvent can count the occurrence of some event and measure both the elapsed time and the thread cpu time of the event.
998 */
999 class PerfTraceElapsedTimeEvent: public PerfTraceElapsedTime {
1000 protected:
1001 PerfLongCounter* _eventp;
1002
1003 public:
1004 inline PerfTraceElapsedTimeEvent(PerfCounter* counter, PerfLongCounter* eventp) : PerfTraceElapsedTime(counter), _eventp(eventp) {
1005 if (!UsePerfData || counter == nullptr) return;
1006 _eventp->inc();
1007 }
1008 };
1009
1010 class PerfTraceThreadTimeEvent: public PerfTraceThreadTime {
1011 protected:
1012 PerfLongCounter* _eventp;
1013
1014 public:
1015 inline PerfTraceThreadTimeEvent(PerfCounter* counter, PerfLongCounter* eventp) : PerfTraceThreadTime(counter), _eventp(eventp) {
1016 if (!UsePerfData || counter == nullptr) return;
1017 _eventp->inc();
1018 }
1019 };
1020
1021 class PerfTraceTimedEvent : public PerfTraceTime {
1022 protected:
1023 PerfLongCounter* _eventp;
1024
1025 public:
1026 inline PerfTraceTimedEvent(PerfTickCounters* counters, PerfLongCounter* eventp, bool is_on = true) : PerfTraceTime(counters, is_on), _eventp(eventp) {
1027 if (!UsePerfData || !is_on || counters == nullptr) return;
1028 _eventp->inc();
1029 }
1030 };
1031 #endif // SHARE_RUNTIME_PERFDATA_HPP
|