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