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 jlong elapsed_counter_value_ms() const;
646 inline jlong elapsed_counter_value_us() const;
647
648 PerfCounter* thread_counter() const {
649 return _thread_counter;
650 }
651 jlong thread_counter_value() const {
652 return _thread_counter->get_value();
653 }
654 inline jlong thread_counter_value_ms() const;
655 inline jlong thread_counter_value_us() const;
656
657 void reset() {
658 _elapsed_counter->reset();
659 _thread_counter->reset();
660 }
661 };
662
663 /*
664 * The PerfDataManager class is responsible for creating PerfData
665 * subtypes via a set a factory methods and for managing lists
666 * of the various PerfData types.
667 */
668 class PerfDataManager : AllStatic {
669
670 friend class StatSampler; // for access to protected PerfDataList methods
671
672 private:
673 static PerfDataList* _all;
674 static PerfDataList* _sampled;
675 static PerfDataList* _constants;
676 static const char* _name_spaces[];
677 static volatile bool _has_PerfData;
678
679 // add a PerfData item to the list(s) of know PerfData objects
680 static void add_item(PerfData* p, bool sampled);
681
806 return create_long_variable(ns, name, u, (jlong)0, THREAD);
807 }
808
809 static PerfVariable* create_variable(CounterNS ns, const char* name,
810 PerfData::Units u,
811 PerfSampleHelper* sh, TRAPS) {
812 return create_long_variable(ns, name, u, sh, THREAD);
813 }
814
815 static PerfCounter* create_counter(CounterNS ns, const char* name,
816 PerfData::Units u, TRAPS) {
817 return create_long_counter(ns, name, u, (jlong)0, THREAD);
818 }
819
820 static PerfCounter* create_counter(CounterNS ns, const char* name,
821 PerfData::Units u,
822 PerfSampleHelper* sh, TRAPS) {
823 return create_long_counter(ns, name, u, sh, THREAD);
824 }
825
826 static PerfTickCounters* create_tick_counters(CounterNS ns,
827 const char* counter_name,
828 const char* elapsed_counter_name,
829 const char* thread_counter_name,
830 PerfData::Units u, TRAPS) {
831 PerfCounter* elapsed_counter = create_long_counter(ns, elapsed_counter_name, u, (jlong)0, THREAD);
832 PerfCounter* thread_counter = create_long_counter(ns, thread_counter_name, u, (jlong)0, THREAD);
833
834 PerfTickCounters* counters = new PerfTickCounters(counter_name, elapsed_counter, thread_counter);
835 return counters;
836 }
837
838 static void destroy();
839 static bool has_PerfData() { return _has_PerfData; }
840 };
841
842 // Useful macros to create the performance counters
843 #define NEWPERFTICKCOUNTER(counter, counter_ns, counter_name) \
844 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
845 PerfData::U_Ticks,CHECK);}
846
847 #define NEWPERFEVENTCOUNTER(counter, counter_ns, counter_name) \
848 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
849 PerfData::U_Events,CHECK);}
850
851 #define NEWPERFBYTECOUNTER(counter, counter_ns, counter_name) \
852 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
853 PerfData::U_Bytes,CHECK);}
854
855 #define NEWPERFTICKCOUNTERS(counter, counter_ns, counter_name) \
856 {counter = PerfDataManager::create_tick_counters(counter_ns, counter_name, counter_name "_elapsed_time", \
857 counter_name "_thread_time", PerfData::U_Ticks,CHECK);}
858
859 // Utility Classes
860
861 /* PerfTraceElapsedTime and PerfTraceThreadTime will administer a PerfCounter used as a time accumulator
862 * for a basic block much like the TraceTime class.
863 * PerfTraceElapsedTime uses elapsedTimer to measure time which reflects the elapsed time,
864 * and PerfTraceThreadTime uses ThreadTimer which reflects thread cpu time.
865 *
866 * Example:
867 *
868 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, 0LL, CHECK);
869 *
870 * {
871 * PerfTraceElapsedTime ptt(my_time_counter);
872 * // perform the operation you want to measure
873 * }
874 *
875 * Note: use of this class does not need to occur within a guarded
876 * block. The UsePerfData guard is used with the implementation
877 * of this class.
878 */
879
880 class PerfTraceTimeBase : public StackObj {
881 friend class PerfPauseTimer;
882 private:
883 BaseTimer* _t;
884 protected:
885 PerfLongCounter* _counter;
886
887 public:
888 inline PerfTraceTimeBase(BaseTimer* t, PerfLongCounter* counter) : _t(t), _counter(counter) {}
889
890 ~PerfTraceTimeBase();
891
892 jlong active_ticks() { return _t->active_ticks(); }
893
894 const char* name() { return _counter->name(); }
895 BaseTimer* timer() { return _t; }
896 };
897
898 class PerfTraceElapsedTime: public PerfTraceTimeBase {
899 protected:
900 elapsedTimer _t;
901
902 public:
903 inline PerfTraceElapsedTime(PerfCounter* counter) : PerfTraceTimeBase(&_t, counter) {
904 if (!UsePerfData || counter == nullptr) { return; }
905 _t.start();
906 }
907 };
908
909 class PerfTraceThreadTime: public PerfTraceTimeBase {
910 protected:
911 ThreadTimer _t;
912
913 public:
914 inline PerfTraceThreadTime(PerfCounter* counter) : PerfTraceTimeBase(&_t, counter) {
915 if (!UsePerfData || !TraceThreadTime || counter == nullptr) { return; }
916 _t.start();
917 }
918 };
919
920 // PerfTraceTime is a utility class to provide the ability to measure both elapsed and thread cpu time using a single object.
921 class PerfTraceTime : public StackObj {
922 friend class PerfPauseTimer;
923 private:
924 PerfTickCounters* _counters;
925 PerfTraceElapsedTime _elapsed_timer;
926 PerfTraceThreadTime _thread_timer;
927
928 public:
929 inline PerfTraceTime(PerfTickCounters* counters, bool is_on = true):
930 _counters(counters),
931 _elapsed_timer(counters != nullptr ? counters->elapsed_counter() : nullptr),
932 _thread_timer(counters != nullptr ? counters->thread_counter() : nullptr) {}
933
934 const char* name() { return _counters->name(); }
935 PerfTraceTimeBase* elapsed_timer() { return &_elapsed_timer; }
936 PerfTraceTimeBase* thread_timer() { return &_thread_timer; }
937
938 jlong elapsed_timer_active_ticks() {
939 return _elapsed_timer.active_ticks();
940 }
941
942 jlong thread_timer_active_ticks() {
943 return _thread_timer.active_ticks();
944 }
945 };
946
947 class PerfPauseTimerBase : public StackObj {
948 protected:
949 bool _is_active;
950 BaseTimer* _timer;
951
952 public:
953 inline PerfPauseTimerBase(PerfTraceTimeBase* timer, bool is_on) : _is_active(false), _timer(nullptr) {
954 _is_active = (is_on && timer != nullptr);
955 if (UsePerfData && _is_active) {
956 _timer = timer->timer();
957 _timer->stop(); // pause
958 }
959 }
960
961 inline ~PerfPauseTimerBase() {
962 if (UsePerfData && _is_active) {
963 assert(_timer != nullptr, "");
964 _timer->start(); // resume
965 }
966 }
967 };
968
969 class PerfPauseTimer : public StackObj {
970 private:
971 PerfPauseTimerBase _elapsed_timer_pause;
972 PerfPauseTimerBase _thread_timer_pause;
973
974 public:
975 inline PerfPauseTimer(PerfTraceTime* timer, bool is_on) :
976 _elapsed_timer_pause(timer != nullptr ? timer->elapsed_timer() : nullptr, is_on),
977 _thread_timer_pause(timer != nullptr ? timer->thread_timer() : nullptr, is_on) {}
978 };
979
980 /* The PerfTraceElapsedTimeEvent class is responsible for counting the
981 * occurrence of some event and measuring the elapsed time of
982 * the event in two separate PerfCounter instances.
983 *
984 * Example:
985 *
986 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, CHECK);
987 * static PerfCounter* my_event_counter = PerfDataManager::create_counter("my.event.counter", PerfData::U_Events, CHECK);
988 *
989 * {
990 * PerfTraceElapsedTimeEvent ptte(my_time_counter, my_event_counter);
991 * // perform the operation you want to count and measure
992 * }
993 *
994 * Note: use of this class does not need to occur within a guarded
995 * block. The UsePerfData guard is used with the implementation
996 * of this class.
997 *
998 * Similarly, PerfTraceThreadTimeEvent can count the occurrence of some event and measure the thread cpu time of the event.
999 * PerfTraceTimedEvent can count the occurrence of some event and measure both the elapsed time and the thread cpu time of the event.
1000 */
1001 class PerfTraceElapsedTimeEvent: public PerfTraceElapsedTime {
1002 protected:
1003 PerfLongCounter* _eventp;
1004
1005 public:
1006 inline PerfTraceElapsedTimeEvent(PerfCounter* counter, PerfLongCounter* eventp) : PerfTraceElapsedTime(counter), _eventp(eventp) {
1007 if (!UsePerfData || counter == nullptr) return;
1008 _eventp->inc();
1009 }
1010 };
1011
1012 class PerfTraceThreadTimeEvent: public PerfTraceThreadTime {
1013 protected:
1014 PerfLongCounter* _eventp;
1015
1016 public:
1017 inline PerfTraceThreadTimeEvent(PerfCounter* counter, PerfLongCounter* eventp) : PerfTraceThreadTime(counter), _eventp(eventp) {
1018 if (!UsePerfData || counter == nullptr) return;
1019 _eventp->inc();
1020 }
1021 };
1022
1023 class PerfTraceTimedEvent : public PerfTraceTime {
1024 protected:
1025 PerfLongCounter* _eventp;
1026
1027 public:
1028 inline PerfTraceTimedEvent(PerfTickCounters* counters, PerfLongCounter* eventp, bool is_on = true) : PerfTraceTime(counters, is_on), _eventp(eventp) {
1029 if (!UsePerfData || !is_on || counters == nullptr) return;
1030 _eventp->inc();
1031 }
1032 };
1033 #endif // SHARE_RUNTIME_PERFDATA_HPP
|