当前位置: 首页 > 工具软件 > Stats > 使用案例 >

StatsCounter

吕英才
2023-12-01

 

//------------------------------------------------------------------------------

// StatsCounter represents a counter in the StatsTable class.

class StatsCounter {

 public:

  // Create a StatsCounter object.

  explicit StatsCounter(const std::string& name)

       : counter_id_(-1) {

    // We prepend the name with 'c:' to indicate that it is a counter.

    name_ = "c:";

    name_.append(name);

  };

 

  virtual ~StatsCounter() {}

 

  // Sets the counter to a specific value.

  void Set(int value) {

    int* loc = GetPtr();

    if (loc) *loc = value;

  }

 

  // Increments the counter.

  void Increment() {

    Add(1);

  }

 

  virtual void Add(int value) {

    int* loc = GetPtr();

    if (loc)

      (*loc) += value;

  }

 

  // Decrements the counter.

  void Decrement() {

    Add(-1);

  }

 

  void Subtract(int value) {

    Add(-value);

  }

 

  // Is this counter enabled?

  // Returns false if table is full.

  bool Enabled() {

    return GetPtr() != NULL;

  }

 

  int value() {

    int* loc = GetPtr();

    if (loc) return *loc;

    return 0;

  }

 

 protected:

  StatsCounter()

    : counter_id_(-1) {

  }

 

  // Returns the cached address of this counter location.

  int* GetPtr() {

    StatsTable* table = StatsTable::current();

    if (!table)

      return NULL;

 

    // If counter_id_ is -1, then we haven't looked it up yet.

    if (counter_id_ == -1) {

      counter_id_ = table->FindCounter(name_);

      if (table->GetSlot() == 0) {

        if (!table->RegisterThread("")) {

          // There is no room for this thread.  This thread

          // cannot use counters.

          counter_id_ = 0;

          return NULL;

        }

      }

    }

 

    // If counter_id_ is > 0, then we have a valid counter.

    if (counter_id_ > 0)

      return table->GetLocation(counter_id_, table->GetSlot());

 

    // counter_id_ was zero, which means the table is full.

    return NULL;

  }

 

  std::string name_;

  // The counter id in the table.  We initialize to -1 (an invalid value)

  // and then cache it once it has been looked up.  The counter_id is

  // valid across all threads and processes.

  int32 counter_id_;

};

 

 

// A StatsCounterTimer is a StatsCounter which keeps a timer during

// the scope of the StatsCounterTimer.  On destruction, it will record

// its time measurement.

class StatsCounterTimer : protected StatsCounter {

 public:

  // Constructs and starts the timer.

  explicit StatsCounterTimer(const std::string& name) {

    // we prepend the name with 't:' to indicate that it is a timer.

    name_ = "t:";

    name_.append(name);

  }

 

  // Start the timer.

  void Start() {

    if (!Enabled())

      return;

    start_time_ = base::TimeTicks::Now();

    stop_time_ = base::TimeTicks();

  }

 

  // Stop the timer and record the results.

  void Stop() {

    if (!Enabled() || !Running())

      return;

    stop_time_ = base::TimeTicks::Now();

    Record();

  }

 

  // Returns true if the timer is running.

  bool Running() {

    return Enabled() && !start_time_.is_null() && stop_time_.is_null();

  }

 

  // Accept a TimeDelta to increment.

  virtual void AddTime(base::TimeDelta time) {

    Add(static_cast<int>(time.InMilliseconds()));

  }

 

 protected:

  // Compute the delta between start and stop, in milliseconds.

  void Record() {

    AddTime(stop_time_ - start_time_);

  }

 

  base::TimeTicks start_time_;

  base::TimeTicks stop_time_;

};

 

// A StatsRate is a timer that keeps a count of the number of intervals added so

// that several statistics can be produced:

//    min, max, avg, count, total

class StatsRate : public StatsCounterTimer {

 public:

  // Constructs and starts the timer.

  explicit StatsRate(const char* name)

      : StatsCounterTimer(name),

      counter_(name),

      largest_add_(std::string(" ").append(name).append("MAX").c_str()) {

  }

 

  virtual void Add(int value) {

    counter_.Increment();

    StatsCounterTimer::Add(value);

    if (value > largest_add_.value())

      largest_add_.Set(value);

  }

 

 private:

  StatsCounter counter_;

  StatsCounter largest_add_;

};

 

 

// Helper class for scoping a timer or rate.

template<class T> class StatsScope {

 public:

  explicit StatsScope<T>(T& timer)

      : timer_(timer) {

    timer_.Start();

  }

 

  ~StatsScope() {

    timer_.Stop();

  }

 

  void Stop() {

    timer_.Stop();

  }

 

 private:

  T& timer_;

};

 

 

 

 

class StatsTable {

 public:

  // Create a new StatsTable.

  // If a StatsTable already exists with the specified name, this StatsTable

  // will use the same shared memory segment as the original.  Otherwise,

  // a new StatsTable is created and all counters are zeroed.

  //

  // name is the name of the StatsTable to use.

  //

  // max_threads is the maximum number of threads the table will support.

  // If the StatsTable already exists, this number is ignored.

  //

  // max_counters is the maximum number of counters the table will support.

  // If the StatsTable already exists, this number is ignored.

  StatsTable(const std::string& name, int max_threads, int max_counters);

 

  // Destroys the StatsTable.  When the last StatsTable is destroyed

  // (across all processes), the StatsTable is removed from disk.

  ~StatsTable();

 

  // For convenience, we create a static table.  This is generally

  // used automatically by the counters.

  static StatsTable* current() { return global_table_; }

 

  // Set the global table for use in this process.

  static void set_current(StatsTable* value) { global_table_ = value; }

 

  // Get the slot id for the calling thread. Returns 0 if no

  // slot is assigned.

  int GetSlot() const;

 

  // All threads that contribute data to the table must register with the

  // table first.  This function will set thread local storage for the

  // thread containing the location in the table where this thread will

  // write its counter data.

  //

  // name is just a debugging tag to label the thread, and it does not

  // need to be unique.  It will be truncated to kMaxThreadNameLength-1

  // characters.

  //

  // On success, returns the slot id for this thread.  On failure,

  // returns 0.

  int RegisterThread(const std::string& name);

 

  // Returns the number of threads currently registered.  This is really not

  // useful except for diagnostics and debugging.

  int CountThreadsRegistered() const;

 

  // Find a counter in the StatsTable.

  //

  // Returns an id for the counter which can be used to call GetLocation().

  // If the counter does not exist, attempts to create a row for the new

  // counter.  If there is no space in the table for the new counter,

  // returns 0.

  int FindCounter(const std::string& name);

 

  // TODO(mbelshe): implement RemoveCounter.

 

  // Gets the location of a particular value in the table based on

  // the counter id and slot id.

  int* GetLocation(int counter_id, int slot_id) const;

 

  // Gets the counter name at a particular row.  If the row is empty,

  // returns NULL.

  const char* GetRowName(int index) const;

 

  // Gets the sum of the values for a particular row.

  int GetRowValue(int index) const;

 

  // Gets the sum of the values for a particular row for a given pid.

  int GetRowValue(int index, int pid) const;

 

  // Gets the sum of the values for a particular counter.  If the counter

  // does not exist, creates the counter.

  int GetCounterValue(const std::string& name);

 

  // Gets the sum of the values for a particular counter for a given pid.

  // If the counter does not exist, creates the counter.

  int GetCounterValue(const std::string& name, int pid);

 

  // The maxinum number of counters/rows in the table.

  int GetMaxCounters() const;

 

  // The maxinum number of threads/columns in the table.

  int GetMaxThreads() const;

 

  // The maximum length (in characters) of a Thread's name including

  // null terminator, as stored in the shared memory.

  static const int kMaxThreadNameLength = 32;

 

  // The maximum length (in characters) of a Counter's name including

  // null terminator, as stored in the shared memory.

  static const int kMaxCounterNameLength = 32;

 

  // Convenience function to lookup a counter location for a

  // counter by name for the calling thread.  Will register

  // the thread if it is not already registered.

  static int* FindLocation(const char *name);

 

 private:

  // Returns the space occupied by a thread in the table.  Generally used

  // if a thread terminates but the process continues.  This function

  // does not zero out the thread's counters.

  // Cannot be used inside a posix tls destructor.

  void UnregisterThread();

 

  // This variant expects the tls data to be passed in, so it is safe to

  // call from inside a posix tls destructor (see doc for pthread_key_create).

  void UnregisterThread(StatsTableTLSData* tls_data);

 

  // The SlotReturnFunction is called at thread exit for each thread

  // which used the StatsTable.

  static void SlotReturnFunction(void* data);

 

  // Locates a free slot in the table.  Returns a number > 0 on success,

  // or 0 on failure.  The caller must hold the shared_memory lock when

  // calling this function.

  int FindEmptyThread() const;

 

  // Locates a counter in the table or finds an empty row.  Returns a

  // number > 0 on success, or 0 on failure.  The caller must hold the

  // shared_memory_lock when calling this function.

  int FindCounterOrEmptyRow(const std::string& name) const;

 

  // Internal function to add a counter to the StatsTable.  Assumes that

  // the counter does not already exist in the table.

  //

  // name is a unique identifier for this counter, and will be truncated

  // to kMaxCounterNameLength-1 characters.

  //

  // On success, returns the counter_id for the newly added counter.

  // On failure, returns 0.

  int AddCounter(const std::string& name);

 

  // Get the TLS data for the calling thread.  Returns NULL if none is

  // initialized.

  StatsTableTLSData* GetTLSData() const;

 

  typedef base::hash_map<std::string, int> CountersMap;

 

  StatsTablePrivate* impl_;

  // The counters_lock_ protects the counters_ hash table.

  Lock counters_lock_;

  // The counters_ hash map is an in-memory hash of the counters.

  // It is used for quick lookup of counters, but is cannot be used

  // as a substitute for what is in the shared memory.  Even though

  // we don't have a counter in our hash table, another process may

  // have created it.

  CountersMap counters_;

  TLSSlot tls_index_;

 

  static StatsTable* global_table_;

 

  DISALLOW_EVIL_CONSTRUCTORS(StatsTable);

};

 

 

 

 

 类似资料:

相关阅读

相关文章

相关问答