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 };
374
375 /*
376 * The PerfLongCounter class, and its alias PerfCounter, implement
377 * a PerfData subtype that holds a jlong data value that can (should)
378 * be modified in a monotonic manner. The inc(jlong) and add(jlong)
379 * methods can be passed negative values to implement a monotonically
380 * decreasing value. However, we rely upon the programmer to honor
381 * the notion that this counter always moves in the same direction -
382 * either increasing or decreasing.
383 */
384 class PerfLongCounter : public PerfLongVariant {
385
386 friend class PerfDataManager; // for access to protected constructor
387
388 protected:
389
390 PerfLongCounter(CounterNS ns, const char* namep, Units u,
391 jlong initial_value=0)
392 : PerfLongVariant(ns, namep, u, V_Monotonic,
541 bool contains(const char* name) { return find_by_name(name) != nullptr; }
542
543 // return the number of PerfData items in this list
544 inline int length();
545
546 // add a PerfData item to this list
547 inline void append(PerfData *p);
548
549 // create a new PerfDataList from this list. The new list is
550 // a shallow copy of the original list and care should be taken
551 // with respect to delete operations on the elements of the list
552 // as the are likely in use by another copy of the list.
553 PerfDataList* clone();
554
555 // for backward compatibility with GrowableArray - need to implement
556 // some form of iterator to provide a cleaner abstraction for
557 // iteration over the container.
558 inline PerfData* at(int index);
559 };
560
561
562 /*
563 * The PerfDataManager class is responsible for creating PerfData
564 * subtypes via a set a factory methods and for managing lists
565 * of the various PerfData types.
566 */
567 class PerfDataManager : AllStatic {
568 private:
569 static PerfDataList* _all;
570 static PerfDataList* _constants;
571 static const char* _name_spaces[];
572 static volatile bool _has_PerfData;
573
574 // add a PerfData item to the list(s) of know PerfData objects
575 static void add_item(PerfData* p);
576
577 static void create_system_property_instrumentation(TRAPS);
578 static void assert_system_property(const char* name, const char* value, TRAPS);
579 static void add_property_constant(CounterNS name_space, const char* name, const char* value, TRAPS);
580 static void add_property_constant(CounterNS name_space, const char* name, TRAPS);
679 static PerfConstant* create_constant(CounterNS ns, const char* name,
680 PerfData::Units u, jlong val, TRAPS) {
681 return create_long_constant(ns, name, u, val, THREAD);
682 }
683
684 static PerfVariable* create_variable(CounterNS ns, const char* name,
685 PerfData::Units u, jlong ival, TRAPS) {
686 return create_long_variable(ns, name, u, ival, THREAD);
687 }
688
689 static PerfVariable* create_variable(CounterNS ns, const char* name,
690 PerfData::Units u, TRAPS) {
691 return create_long_variable(ns, name, u, (jlong)0, THREAD);
692 }
693
694 static PerfCounter* create_counter(CounterNS ns, const char* name,
695 PerfData::Units u, TRAPS) {
696 return create_long_counter(ns, name, u, (jlong)0, THREAD);
697 }
698
699 static void destroy();
700 static bool has_PerfData() { return AtomicAccess::load_acquire(&_has_PerfData); }
701 };
702
703 // Useful macros to create the performance counters
704 #define NEWPERFTICKCOUNTER(counter, counter_ns, counter_name) \
705 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
706 PerfData::U_Ticks,CHECK);}
707
708 #define NEWPERFEVENTCOUNTER(counter, counter_ns, counter_name) \
709 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
710 PerfData::U_Events,CHECK);}
711
712 #define NEWPERFBYTECOUNTER(counter, counter_ns, counter_name) \
713 {counter = PerfDataManager::create_counter(counter_ns, counter_name, \
714 PerfData::U_Bytes,CHECK);}
715
716 // Utility Classes
717
718 /*
719 * This class will administer a PerfCounter used as a time accumulator
720 * for a basic block much like the TraceTime class.
721 *
722 * Example:
723 *
724 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, 0LL, CHECK);
725 *
726 * {
727 * PerfTraceTime ptt(my_time_counter);
728 * // perform the operation you want to measure
729 * }
730 *
731 * Note: use of this class does not need to occur within a guarded
732 * block. The UsePerfData guard is used with the implementation
733 * of this class.
734 *
735 * But also note this class does not guard against shutdown races -
736 * see SafePerfTraceTime below.
737 */
738 class PerfTraceTime : public StackObj {
739
740 protected:
741 elapsedTimer _t;
742 PerfLongCounter* _timerp;
743
744 public:
745 inline PerfTraceTime(PerfLongCounter* timerp) : _timerp(timerp) {
746 if (!UsePerfData || timerp == nullptr) { return; }
747 _t.start();
748 }
749
750 const char* name() const {
751 assert(_timerp != nullptr, "sanity");
752 return _timerp->name();
753 }
754
755 ~PerfTraceTime() {
756 if (!UsePerfData || !_t.is_active()) { return; }
757 _t.stop();
758 _timerp->inc(_t.ticks());
759 }
760 };
761
762 /* A variant of PerfTraceTime that guards against use during shutdown -
763 * see PerfDataManager::destroy.
764 */
765 class SafePerfTraceTime : public StackObj {
766
767 protected:
768 elapsedTimer _t;
769 PerfLongCounter* _timerp;
770
771 public:
772 inline SafePerfTraceTime(PerfLongCounter* timerp);
773
774 const char* name() const {
775 assert(_timerp != nullptr, "sanity");
776 return _timerp->name();
777 }
778
779 inline ~SafePerfTraceTime();
780 };
781
782 /* The PerfTraceTimedEvent class is responsible for counting the
783 * occurrence of some event and measuring the elapsed time of
784 * the event in two separate PerfCounter instances.
785 *
786 * Example:
787 *
788 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, CHECK);
789 * static PerfCounter* my_event_counter = PerfDataManager::create_counter("my.event.counter", PerfData::U_Events, CHECK);
790 *
791 * {
792 * PerfTraceTimedEvent ptte(my_time_counter, my_event_counter);
793 * // perform the operation you want to count and measure
794 * }
795 *
796 * Note: use of this class does not need to occur within a guarded
797 * block. The UsePerfData guard is used with the implementation
798 * of this class.
799 *
800 */
801 class PerfTraceTimedEvent : public PerfTraceTime {
802
803 protected:
804 PerfLongCounter* _eventp;
805
806 public:
807 inline PerfTraceTimedEvent(PerfLongCounter* timerp, PerfLongCounter* eventp): PerfTraceTime(timerp), _eventp(eventp) {
808 if (!UsePerfData || timerp == nullptr) { return; }
809 _eventp->inc();
810 }
811
812 };
813
814 #endif // SHARE_RUNTIME_PERFDATA_HPP
|
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,
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);
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 /*
771 * This class will administer a PerfCounter used as a time accumulator
772 * for a basic block much like the TraceTime class.
773 * PerfTraceElapsedTime uses elapsedTimer to measure time which reflects the elapsed time,
774 * and PerfTraceThreadTime uses ThreadTimer which reflects thread cpu time.
775 *
776 * Example:
777 *
778 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, 0LL, CHECK);
779 *
780 * {
781 * PerfTraceElapsedTime ptt(my_time_counter);
782 * // perform the operation you want to measure
783 * }
784 *
785 * Note: use of this class does not need to occur within a guarded
786 * block. The UsePerfData guard is used with the implementation
787 * of this class.
788 *
789 * But also note this class does not guard against shutdown races -
790 * see SafePerfTraceTime below.
791 */
792
793 class PerfTraceTimeBase : public StackObj {
794 friend class PerfPauseTimer;
795 private:
796 BaseTimer* _t;
797 protected:
798 PerfLongCounter* _counter;
799
800 public:
801 inline PerfTraceTimeBase(BaseTimer* t, PerfLongCounter* counter) : _t(t), _counter(counter) {}
802
803 ~PerfTraceTimeBase();
804
805 jlong active_ticks() { return _t->active_ticks(); }
806
807 const char* name() { return _counter->name(); }
808 BaseTimer* timer() { return _t; }
809 };
810
811 class PerfTraceElapsedTime: public PerfTraceTimeBase {
812 protected:
813 elapsedTimer _t;
814
815 public:
816 inline PerfTraceElapsedTime(PerfCounter* counter) : PerfTraceTimeBase(&_t, counter) {
817 if (!UsePerfData || counter == nullptr) { return; }
818 _t.start();
819 }
820 };
821
822 class PerfTraceThreadTime: public PerfTraceTimeBase {
823 protected:
824 ThreadTimer _t;
825
826 public:
827 inline PerfTraceThreadTime(PerfCounter* counter) : PerfTraceTimeBase(&_t, counter) {
828 if (!UsePerfData || !TraceThreadTime || counter == nullptr) { return; }
829 _t.start();
830 }
831 };
832
833 // PerfTraceTime is a utility class to provide the ability to measure both elapsed and thread cpu time using a single object.
834 class PerfTraceTime : public StackObj {
835 friend class PerfPauseTimer;
836 private:
837 PerfTickCounters* _counters;
838 PerfTraceElapsedTime _elapsed_timer;
839 PerfTraceThreadTime _thread_timer;
840
841 public:
842 inline PerfTraceTime(PerfTickCounters* counters, bool is_on = true):
843 _counters(counters),
844 _elapsed_timer(counters != nullptr ? counters->elapsed_counter() : nullptr),
845 _thread_timer(counters != nullptr ? counters->thread_counter() : nullptr) {}
846
847 const char* name() { return _counters->name(); }
848 PerfTraceTimeBase* elapsed_timer() { return &_elapsed_timer; }
849 PerfTraceTimeBase* thread_timer() { return &_thread_timer; }
850
851 jlong elapsed_timer_active_ticks() {
852 return _elapsed_timer.active_ticks();
853 }
854
855 jlong thread_timer_active_ticks() {
856 return _thread_timer.active_ticks();
857 }
858 };
859
860 class PerfPauseTimerBase : public StackObj {
861 protected:
862 bool _is_active;
863 BaseTimer* _timer;
864
865 public:
866 inline PerfPauseTimerBase(PerfTraceTimeBase* timer, bool is_on) : _is_active(false), _timer(nullptr) {
867 _is_active = (is_on && timer != nullptr);
868 if (UsePerfData && _is_active) {
869 _timer = timer->timer();
870 _timer->stop(); // pause
871 }
872 }
873
874 inline ~PerfPauseTimerBase() {
875 if (UsePerfData && _is_active) {
876 assert(_timer != nullptr, "");
877 _timer->start(); // resume
878 }
879 }
880 };
881
882 class PerfPauseTimer : public StackObj {
883 private:
884 PerfPauseTimerBase _elapsed_timer_pause;
885 PerfPauseTimerBase _thread_timer_pause;
886
887 public:
888 inline PerfPauseTimer(PerfTraceTime* timer, bool is_on) :
889 _elapsed_timer_pause(timer != nullptr ? timer->elapsed_timer() : nullptr, is_on),
890 _thread_timer_pause(timer != nullptr ? timer->thread_timer() : nullptr, is_on) {}
891 };
892
893 /* A variant of PerfTraceTime that guards against use during shutdown -
894 * see PerfDataManager::destroy.
895 */
896 class SafePerfTraceTime : public StackObj {
897
898 protected:
899 elapsedTimer _t;
900 PerfLongCounter* _timerp;
901
902 public:
903 inline SafePerfTraceTime(PerfLongCounter* timerp);
904
905 const char* name() const {
906 assert(_timerp != nullptr, "sanity");
907 return _timerp->name();
908 }
909
910 inline ~SafePerfTraceTime();
911 };
912
913 /* The PerfTraceTimedEvent class is responsible for counting the
914 * occurrence of some event and measuring the elapsed time of
915 * the event in two separate PerfCounter instances.
916 *
917 * Example:
918 *
919 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, CHECK);
920 * static PerfCounter* my_event_counter = PerfDataManager::create_counter("my.event.counter", PerfData::U_Events, CHECK);
921 *
922 * {
923 * PerfTraceElapsedTimeEvent ptte(my_time_counter, my_event_counter);
924 * // perform the operation you want to count and measure
925 * }
926 *
927 * Note: use of this class does not need to occur within a guarded
928 * block. The UsePerfData guard is used with the implementation
929 * of this class.
930 *
931 * Similarly, PerfTraceThreadTimeEvent can count the occurrence of some event and measure the thread cpu time of the event.
932 * PerfTraceTimedEvent can count the occurrence of some event and measure both the elapsed time and the thread cpu time of the event.
933 */
934 class PerfTraceElapsedTimeEvent: public PerfTraceElapsedTime {
935 protected:
936 PerfLongCounter* _eventp;
937
938 public:
939 inline PerfTraceElapsedTimeEvent(PerfCounter* counter, PerfLongCounter* eventp) : PerfTraceElapsedTime(counter), _eventp(eventp) {
940 if (!UsePerfData || counter == nullptr) return;
941 _eventp->inc();
942 }
943 };
944
945 class PerfTraceThreadTimeEvent: public PerfTraceThreadTime {
946 protected:
947 PerfLongCounter* _eventp;
948
949 public:
950 inline PerfTraceThreadTimeEvent(PerfCounter* counter, PerfLongCounter* eventp) : PerfTraceThreadTime(counter), _eventp(eventp) {
951 if (!UsePerfData || counter == nullptr) return;
952 _eventp->inc();
953 }
954 };
955
956 class PerfTraceTimedEvent : public PerfTraceTime {
957 protected:
958 PerfLongCounter* _eventp;
959
960 public:
961 inline PerfTraceTimedEvent(PerfTickCounters* counters, PerfLongCounter* eventp, bool is_on = true) : PerfTraceTime(counters, is_on), _eventp(eventp) {
962 if (!UsePerfData || !is_on || counters == nullptr) return;
963 _eventp->inc();
964 }
965 };
966 #endif // SHARE_RUNTIME_PERFDATA_HPP
|