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 Atomic::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 class PerfTraceTime : public StackObj {
736
737 protected:
738 elapsedTimer _t;
739 PerfLongCounter* _timerp;
740
741 public:
742 inline PerfTraceTime(PerfLongCounter* timerp) : _timerp(timerp) {
743 if (!UsePerfData || timerp == nullptr) { return; }
744 _t.start();
745 }
746
747 const char* name() const {
748 assert(_timerp != nullptr, "sanity");
749 return _timerp->name();
750 }
751
752 ~PerfTraceTime() {
753 if (!UsePerfData || !_t.is_active()) { return; }
754 _t.stop();
755 _timerp->inc(_t.ticks());
756 }
757 };
758
759 /* The PerfTraceTimedEvent class is responsible for counting the
760 * occurrence of some event and measuring the elapsed time of
761 * the event in two separate PerfCounter instances.
762 *
763 * Example:
764 *
765 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, CHECK);
766 * static PerfCounter* my_event_counter = PerfDataManager::create_counter("my.event.counter", PerfData::U_Events, CHECK);
767 *
768 * {
769 * PerfTraceTimedEvent ptte(my_time_counter, my_event_counter);
770 * // perform the operation you want to count and measure
771 * }
772 *
773 * Note: use of this class does not need to occur within a guarded
774 * block. The UsePerfData guard is used with the implementation
775 * of this class.
776 *
777 */
778 class PerfTraceTimedEvent : public PerfTraceTime {
779
780 protected:
781 PerfLongCounter* _eventp;
782
783 public:
784 inline PerfTraceTimedEvent(PerfLongCounter* timerp, PerfLongCounter* eventp): PerfTraceTime(timerp), _eventp(eventp) {
785 if (!UsePerfData || timerp == nullptr) { return; }
786 _eventp->inc();
787 }
788
789 };
790
791 #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 Atomic::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 /* PerfTraceElapsedTime and PerfTraceThreadTime will administer a PerfCounter used as a time accumulator
771 * for a basic block much like the TraceTime class.
772 * PerfTraceElapsedTime uses elapsedTimer to measure time which reflects the elapsed time,
773 * and PerfTraceThreadTime uses ThreadTimer which reflects thread cpu time.
774 *
775 * Example:
776 *
777 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, 0LL, CHECK);
778 *
779 * {
780 * PerfTraceElapsedTime ptt(my_time_counter);
781 * // perform the operation you want to measure
782 * }
783 *
784 * Note: use of this class does not need to occur within a guarded
785 * block. The UsePerfData guard is used with the implementation
786 * of this class.
787 */
788
789 class PerfTraceTimeBase : public StackObj {
790 friend class PerfPauseTimer;
791 private:
792 BaseTimer* _t;
793 protected:
794 PerfLongCounter* _counter;
795
796 public:
797 inline PerfTraceTimeBase(BaseTimer* t, PerfLongCounter* counter) : _t(t), _counter(counter) {}
798
799 ~PerfTraceTimeBase();
800
801 jlong active_ticks() { return _t->active_ticks(); }
802
803 const char* name() { return _counter->name(); }
804 BaseTimer* timer() { return _t; }
805 };
806
807 class PerfTraceElapsedTime: public PerfTraceTimeBase {
808 protected:
809 elapsedTimer _t;
810
811 public:
812 inline PerfTraceElapsedTime(PerfCounter* counter) : PerfTraceTimeBase(&_t, counter) {
813 if (!UsePerfData || counter == nullptr) { return; }
814 _t.start();
815 }
816 };
817
818 class PerfTraceThreadTime: public PerfTraceTimeBase {
819 protected:
820 ThreadTimer _t;
821
822 public:
823 inline PerfTraceThreadTime(PerfCounter* counter) : PerfTraceTimeBase(&_t, counter) {
824 if (!UsePerfData || !TraceThreadTime || counter == nullptr) { return; }
825 _t.start();
826 }
827 };
828
829 // PerfTraceTime is a utility class to provide the ability to measure both elapsed and thread cpu time using a single object.
830 class PerfTraceTime : public StackObj {
831 friend class PerfPauseTimer;
832 private:
833 PerfTickCounters* _counters;
834 PerfTraceElapsedTime _elapsed_timer;
835 PerfTraceThreadTime _thread_timer;
836
837 public:
838 inline PerfTraceTime(PerfTickCounters* counters, bool is_on = true):
839 _counters(counters),
840 _elapsed_timer(counters != nullptr ? counters->elapsed_counter() : nullptr),
841 _thread_timer(counters != nullptr ? counters->thread_counter() : nullptr) {}
842
843 const char* name() { return _counters->name(); }
844 PerfTraceTimeBase* elapsed_timer() { return &_elapsed_timer; }
845 PerfTraceTimeBase* thread_timer() { return &_thread_timer; }
846
847 jlong elapsed_timer_active_ticks() {
848 return _elapsed_timer.active_ticks();
849 }
850
851 jlong thread_timer_active_ticks() {
852 return _thread_timer.active_ticks();
853 }
854 };
855
856 class PerfPauseTimerBase : public StackObj {
857 protected:
858 bool _is_active;
859 BaseTimer* _timer;
860
861 public:
862 inline PerfPauseTimerBase(PerfTraceTimeBase* timer, bool is_on) : _is_active(false), _timer(nullptr) {
863 _is_active = (is_on && timer != nullptr);
864 if (UsePerfData && _is_active) {
865 _timer = timer->timer();
866 _timer->stop(); // pause
867 }
868 }
869
870 inline ~PerfPauseTimerBase() {
871 if (UsePerfData && _is_active) {
872 assert(_timer != nullptr, "");
873 _timer->start(); // resume
874 }
875 }
876 };
877
878 class PerfPauseTimer : public StackObj {
879 private:
880 PerfPauseTimerBase _elapsed_timer_pause;
881 PerfPauseTimerBase _thread_timer_pause;
882
883 public:
884 inline PerfPauseTimer(PerfTraceTime* timer, bool is_on) :
885 _elapsed_timer_pause(timer != nullptr ? timer->elapsed_timer() : nullptr, is_on),
886 _thread_timer_pause(timer != nullptr ? timer->thread_timer() : nullptr, is_on) {}
887 };
888
889 /* The PerfTraceElapsedTimeEvent class is responsible for counting the
890 * occurrence of some event and measuring the elapsed time of
891 * the event in two separate PerfCounter instances.
892 *
893 * Example:
894 *
895 * static PerfCounter* my_time_counter = PerfDataManager::create_counter("my.time.counter", PerfData::U_Ticks, CHECK);
896 * static PerfCounter* my_event_counter = PerfDataManager::create_counter("my.event.counter", PerfData::U_Events, CHECK);
897 *
898 * {
899 * PerfTraceElapsedTimeEvent ptte(my_time_counter, my_event_counter);
900 * // perform the operation you want to count and measure
901 * }
902 *
903 * Note: use of this class does not need to occur within a guarded
904 * block. The UsePerfData guard is used with the implementation
905 * of this class.
906 *
907 * Similarly, PerfTraceThreadTimeEvent can count the occurrence of some event and measure the thread cpu time of the event.
908 * PerfTraceTimedEvent can count the occurrence of some event and measure both the elapsed time and the thread cpu time of the event.
909 */
910 class PerfTraceElapsedTimeEvent: public PerfTraceElapsedTime {
911 protected:
912 PerfLongCounter* _eventp;
913
914 public:
915 inline PerfTraceElapsedTimeEvent(PerfCounter* counter, PerfLongCounter* eventp) : PerfTraceElapsedTime(counter), _eventp(eventp) {
916 if (!UsePerfData || counter == nullptr) return;
917 _eventp->inc();
918 }
919 };
920
921 class PerfTraceThreadTimeEvent: public PerfTraceThreadTime {
922 protected:
923 PerfLongCounter* _eventp;
924
925 public:
926 inline PerfTraceThreadTimeEvent(PerfCounter* counter, PerfLongCounter* eventp) : PerfTraceThreadTime(counter), _eventp(eventp) {
927 if (!UsePerfData || counter == nullptr) return;
928 _eventp->inc();
929 }
930 };
931
932 class PerfTraceTimedEvent : public PerfTraceTime {
933 protected:
934 PerfLongCounter* _eventp;
935
936 public:
937 inline PerfTraceTimedEvent(PerfTickCounters* counters, PerfLongCounter* eventp, bool is_on = true) : PerfTraceTime(counters, is_on), _eventp(eventp) {
938 if (!UsePerfData || !is_on || counters == nullptr) return;
939 _eventp->inc();
940 }
941 };
942 #endif // SHARE_RUNTIME_PERFDATA_HPP
|