< prev index next >

src/hotspot/share/runtime/perfData.hpp

Print this page

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