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