< prev index next >

src/hotspot/share/runtime/perfData.hpp

Print this page

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
< prev index next >