Repository: google/benchmark
File: src/perf_counters.cc (C++)

Code before:
  size_t size = bufsize;
  for (int lead : leaders) {
    auto read_bytes = ::read(lead, ptr, size);
    if (read_bytes >= ssize_t(sizeof(uint64_t))) {
      // Actual data bytes are all bytes minus initial padding
      std::size_t data_bytes = read_bytes - sizeof(uint64_t);
      // This should be very cheap since it's in hot cache
      std::memmove(ptr, ptr + sizeof(uint64_t), data_bytes);
      // Increment our counters
      ptr += data_bytes;
      size -= data_bytes;
    } else {
      int err = errno;
      GetErrorLogInstance() << "Error reading lead " << lead << " errno:" << err
                            << " " << ::strerror(err) << "\n";
      return 0;
    }
  }
  return (bufsize - size) / sizeof(uint64_t);
}

const bool PerfCounters::kSupported = true;

// Initializes libpfm only on the first call.  Returns whether that single
// initialization was successful
static bool InitLibPfmOnce() {
  // Function-scope static gets initialized only once on first call.
  static const bool success = []() {
    return pfm_initialize() == PFM_SUCCESS;
  }();
  return success;
}

bool PerfCounters::Initialize() { return InitLibPfmOnce(); }

bool PerfCounters::IsCounterSupported(const std::string& name) {
  InitLibPfmOnce();
  perf_event_attr_t attr;
  std::memset(&attr, 0, sizeof(attr));
  pfm_perf_encode_arg_t arg;
  std::memset(&arg, 0, sizeof(arg));
  arg.attr = &attr;
  const int mode = PFM_PLM3;  // user mode only
  int ret = pfm_get_os_event_encoding(name.c_str(), mode, PFM_OS_PERF_EVENT_EXT,
                                      &arg);
  return (ret == PFM_SUCCESS);
}

PerfCounters PerfCounters::Create(
    const std::vector<std::string>& counter_names) {
  if (!counter_names.empty()) {

Review comment (suggestion):
I could also delete `InitLibPfmOnce` and put this directly in `Initialize`.

I thought it was clearer to have the other calls use this name, though.

Code after:
  size_t size = bufsize;
  for (int lead : leaders) {
    auto read_bytes = ::read(lead, ptr, size);
    if (read_bytes >= ssize_t(sizeof(uint64_t))) {
      // Actual data bytes are all bytes minus initial padding
      std::size_t data_bytes = read_bytes - sizeof(uint64_t);
      // This should be very cheap since it's in hot cache
      std::memmove(ptr, ptr + sizeof(uint64_t), data_bytes);
      // Increment our counters
      ptr += data_bytes;
      size -= data_bytes;
    } else {
      int err = errno;
      GetErrorLogInstance() << "Error reading lead " << lead << " errno:" << err
                            << " " << ::strerror(err) << "\n";
      return 0;
    }
  }
  return (bufsize - size) / sizeof(uint64_t);
}

const bool PerfCounters::kSupported = true;

// Initializes libpfm only on the first call.  Returns whether that single
// initialization was successful.
bool PerfCounters::Initialize() {
  // Function-scope static gets initialized only once on first call.
  static const bool success = []() {
    return pfm_initialize() == PFM_SUCCESS;
  }();
  return success;
}

bool PerfCounters::IsCounterSupported(const std::string& name) {
  Initialize();
  perf_event_attr_t attr;
  std::memset(&attr, 0, sizeof(attr));
  pfm_perf_encode_arg_t arg;
  std::memset(&arg, 0, sizeof(arg));
  arg.attr = &attr;
  const int mode = PFM_PLM3;  // user mode only
  int ret = pfm_get_os_event_encoding(name.c_str(), mode, PFM_OS_PERF_EVENT_EXT,
                                      &arg);
  return (ret == PFM_SUCCESS);
}

PerfCounters PerfCounters::Create(
    const std::vector<std::string>& counter_names) {
  if (!counter_names.empty()) {
    Initialize();
  }