blob: 23594cc7c2eea0c7757f44e8640f37c088ebc9a2 [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// -*- mode: C++ -*-
//
// Copyright 2021-2022 Google LLC
//
// Licensed under the Apache License v2.0 with LLVM Exceptions (the
// "License"); you may not use this file except in compliance with the
// License. You may obtain a copy of the License at
//
// https://llvm.org/LICENSE.txt
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Giuliano Procida
#include "metrics.h"
#include <cstddef>
#include <iomanip>
#include <map>
#include <ostream>
#include <utility>
#include <variant>
namespace stg {
namespace {
std::ostream& operator<<(std::ostream& os, std::monostate) {
return os << "<incomplete>";
}
std::ostream& operator<<(std::ostream& os,
const std::map<size_t, size_t>& frequencies) {
bool separate = false;
for (const auto& [item, frequency] : frequencies) {
if (separate) {
os << ' ';
} else {
separate = true;
}
os << '[' << item << "]=" << frequency;
}
return os;
}
std::ostream& operator<<(std::ostream& os, const Nanoseconds& value) {
const auto millis = value.ns / 1'000'000;
const auto nanos = value.ns % 1'000'000;
// fill needs to be reset; width is reset automatically
return os << millis << '.' << std::setfill('0') << std::setw(6) << nanos
<< std::setfill(' ') << " ms";
}
} // namespace
void Report(const Metrics& metrics, std::ostream& os) {
for (const auto& metric : metrics) {
std::visit([&](auto&& value) {
os << metric.name << ": " << value << '\n';
}, metric.value);
}
}
Time::Time(Metrics& metrics, const char* name)
: metrics_(metrics), index_(metrics.size()) {
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_);
metrics_.push_back(Metric{name, std::monostate()});
}
Time::~Time() {
struct timespec finish;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &finish);
const auto seconds = finish.tv_sec - start_.tv_sec;
const auto nanos = finish.tv_nsec - start_.tv_nsec;
metrics_[index_].value.emplace<1>(seconds * 1'000'000'000 + nanos);
}
Counter::Counter(Metrics& metrics, const char* name)
: metrics_(metrics), index_(metrics.size()), value_(0) {
metrics_.push_back(Metric{name, std::monostate()});
}
Counter::~Counter() {
metrics_[index_].value = value_;
}
Histogram::Histogram(Metrics& metrics, const char* name)
: metrics_(metrics), index_(metrics.size()) {
metrics_.push_back(Metric{name, std::monostate()});
}
Histogram::~Histogram() {
metrics_[index_].value.emplace<3>(std::move(frequencies_));
}
} // namespace stg