Repository: carbon-language/carbon-lang
File: toolchain/base/timings.h (C/C++)

Code before:

namespace Carbon {

// Helps track timings for a compile.
class Timings {
 public:
  // Records a timing for a scope, if the timings object is present.
  class ScopedTiming {
   public:
    // The `timings` may be null, in which case the `ScopedTiming` is a no-op.
    explicit ScopedTiming(Timings* timings, llvm::StringRef label)
        : timings(timings),
          label(label),
          start(timings ? std::chrono::steady_clock::now()
                        : std::chrono::steady_clock::time_point::min()) {}

    ~ScopedTiming() {
      if (timings) {
        timings->Add(label, std::chrono::steady_clock::now() - start);
      }
    }

   private:
    Timings* timings;
    llvm::StringRef label;
    std::chrono::steady_clock::time_point start;
  };

  // Adds tracking for nanoseconds, paired with the given label.
  auto Add(llvm::StringRef label, std::chrono::nanoseconds nanoseconds)
      -> void {
    timings_.push_back(
        {.label = std::string(label), .nanoseconds = nanoseconds});
  }

  auto OutputYaml(llvm::StringRef filename) const -> Yaml::OutputMapping {
    // Explicitly copy the filename.
    return Yaml::OutputMapping([&, filename](Yaml::OutputMapping::Map map) {
      map.Add("filename", filename);
      map.Add("nanoseconds",
              Yaml::OutputMapping([&](Yaml::OutputMapping::Map label_map) {
                std::chrono::nanoseconds total_nanoseconds(0);
                for (const auto& entry : timings_) {
                  total_nanoseconds += entry.nanoseconds;
                  label_map.Add(entry.label, static_cast<int64_t>(
                                                 entry.nanoseconds.count()));
                }
                label_map.Add("Total",
                              static_cast<int64_t>(total_nanoseconds.count()));
              }));
    });

Review comment (refactor):
Small thing while you're in here, I should've had these class members named with underscores (`timings_` etc). Would you be okay fixing that as long as you're refactoring here? (if you'd rather not, feel free to merge without it)

Code after:

namespace Carbon {

// Helps track timings for a compile.
class Timings {
 public:
  // Records a timing for a scope, if the timings object is present.
  class ScopedTiming {
   public:
    // The `timings` may be null, in which case the `ScopedTiming` is a no-op.
    explicit ScopedTiming(Timings* timings, llvm::StringRef label)
        : timings_(timings),
          label_(label),
          start_(timings ? std::chrono::steady_clock::now()
                         : std::chrono::steady_clock::time_point::min()) {}

    ~ScopedTiming() {
      if (timings_) {
        timings_->Add(label_, std::chrono::steady_clock::now() - start_);
      }
    }

   private:
    Timings* timings_;
    llvm::StringRef label_;
    std::chrono::steady_clock::time_point start_;
  };

  // Adds tracking for nanoseconds, paired with the given label.
  auto Add(llvm::StringRef label, std::chrono::nanoseconds nanoseconds)
      -> void {
    timings_.push_back(
        {.label = std::string(label), .nanoseconds = nanoseconds});
  }

  auto OutputYaml(llvm::StringRef filename) const -> Yaml::OutputMapping {
    // Explicitly copy the filename.
    return Yaml::OutputMapping([&, filename](Yaml::OutputMapping::Map map) {
      map.Add("filename", filename);
      map.Add("nanoseconds",
              Yaml::OutputMapping([&](Yaml::OutputMapping::Map label_map) {
                std::chrono::nanoseconds total_nanoseconds(0);
                for (const auto& entry : timings_) {
                  total_nanoseconds += entry.nanoseconds;
                  label_map.Add(entry.label, static_cast<int64_t>(
                                                 entry.nanoseconds.count()));
                }
                label_map.Add("Total",
                              static_cast<int64_t>(total_nanoseconds.count()));
              }));
    });