Repository: google/benchmark
File: include/benchmark/benchmark.h (C/C++)

Code before:
  void SetLabel(const char* label);

  void BENCHMARK_ALWAYS_INLINE SetLabel(const std::string& str) {
    this->SetLabel(str.c_str());
  }

  // Range arguments for this run. CHECKs if the argument has been set.
  BENCHMARK_ALWAYS_INLINE
  int range(std::size_t pos = 0) const {
    assert(range_.size() > pos);
    return range_[pos];
  }

  BENCHMARK_DEPRECATED_MSG("use 'range(0)' instead")
  int range_x() const { return range(0); }

  BENCHMARK_DEPRECATED_MSG("use 'range(1)' instead")
  int range_y() const { return range(1); }

  BENCHMARK_ALWAYS_INLINE
  size_t iterations() const {
    return (max_iterations - total_iterations_ + batch_leftover_);
  }

private: // items we expect on the first cache line (ie 64 bytes of the struct)
  bool started_ : 1;
  bool finished_ : 1;
  bool error_occurred_ : 1;
  // When total_iterations_ is 0, KeepRunning() and friends will return false.
  // May be larger than max_iterations.
  size_t total_iterations_;

  // When using KeepRunningBatch(), batch_leftover_ holds the number of
  // iterations beyond max_iters that were run. Used to track
  // completed_iterations_ accurately.
  size_t batch_leftover_;

public:
  const size_t max_iterations;

private: // items we don't need on the first cache line
  std::vector<int> range_;

  size_t bytes_processed_;
  size_t items_processed_;

  int complexity_n_;

 public:
  // Container for user-defined counters.
  UserCounters counters;

Review comment (performance):
how about not doing this yet, but adding a "TODO: make these bitfields if required".

reasoning: on some platforms (at least this used to be true), bitfield accesses required quite a bit more ASM than bool accesses. Ie, the bitfield work might negate the work to get these in the cache line in the first place.

Code after:
  void SetLabel(const char* label);

  void BENCHMARK_ALWAYS_INLINE SetLabel(const std::string& str) {
    this->SetLabel(str.c_str());
  }

  // Range arguments for this run. CHECKs if the argument has been set.
  BENCHMARK_ALWAYS_INLINE
  int range(std::size_t pos = 0) const {
    assert(range_.size() > pos);
    return range_[pos];
  }

  BENCHMARK_DEPRECATED_MSG("use 'range(0)' instead")
  int range_x() const { return range(0); }

  BENCHMARK_DEPRECATED_MSG("use 'range(1)' instead")
  int range_y() const { return range(1); }

  BENCHMARK_ALWAYS_INLINE
  size_t iterations() const {
    return (max_iterations - total_iterations_ + batch_leftover_);
  }

private: // items we expect on the first cache line (ie 64 bytes of the struct)

  // When total_iterations_ is 0, KeepRunning() and friends will return false.
  // May be larger than max_iterations.
  size_t total_iterations_;

  // When using KeepRunningBatch(), batch_leftover_ holds the number of
  // iterations beyond max_iters that were run. Used to track
  // completed_iterations_ accurately.
  size_t batch_leftover_;

public:
  const size_t max_iterations;

private:
  bool started_;
  bool finished_;
  bool error_occurred_;

private: // items we don't need on the first cache line
  std::vector<int> range_;

  size_t bytes_processed_;
  size_t items_processed_;

  int complexity_n_;