xref: /5.5.2/platform/src/histogram.cc (revision 9c83cef1)
1/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *     Copyright 2017 Couchbase, Inc
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 */
17
18#include <platform/histogram.h>
19
20/*
21 * Histogram<> definitions of large methods which we prefer to not inline.
22 */
23
24template <typename T, template <class> class Limits>
25void Histogram<T, Limits>::add(T amount, size_t count) {
26    (*findBin(amount))->incr(count);
27}
28
29template <typename T, template <class> class Limits>
30void Histogram<T, Limits>::reset() {
31    std::for_each(bins.begin(), bins.end(),
32                  [](value_type& val){val->set(0);});
33}
34
35template <typename T, template <class> class Limits>
36size_t Histogram<T, Limits>::total() {
37    HistogramBinSampleAdder<T, Limits> a;
38    return std::accumulate(begin(), end(), 0, a);
39}
40
41template <typename T, template <class> class Limits>
42bool Histogram<T, Limits>::verify() {
43    T prev = Limits<T>::min();
44    int pos(0);
45    for (const auto& bin : bins) {
46        if (bin->start() != prev) {
47            std::cerr << "Expected " << bin->start() << " == " << prev
48                      << " at pos " << pos << std::endl;
49            return false;
50        }
51        if (bin->start() != prev) {
52            return false;
53        }
54        prev = bin->end();
55        ++pos;
56    }
57    if (prev != Limits<T>::max()) {
58        return false;
59    }
60    return true;
61}
62
63template <typename T, template <class> class Limits>
64typename Histogram<T, Limits>::iterator Histogram<T, Limits>::findBin(
65        T amount) {
66    if (amount == Limits<T>::max()) {
67        return bins.end() - 1;
68    } else {
69        iterator it;
70        it = std::upper_bound(bins.begin(),
71                              bins.end(),
72                              amount,
73                              [](T t, Histogram<T, Limits>::value_type& b) {
74                                  return t < b->end();
75                              });
76        if (!(*it)->accepts(amount)) {
77            return bins.end();
78        }
79        return it;
80    }
81}
82
83// Explicit template instantiations for all classes which we specialise
84// Histogram<> for.
85template class PLATFORM_PUBLIC_API Histogram<uint16_t>;
86template class PLATFORM_PUBLIC_API Histogram<uint32_t>;
87template class PLATFORM_PUBLIC_API Histogram<size_t>;
88template class PLATFORM_PUBLIC_API Histogram<int>;
89template class PLATFORM_PUBLIC_API Histogram<UnsignedMicroseconds, cb::duration_limits>;
90
91// This is non-inline because it requires the definition of histogram and hence
92// if inline would trigger an implicit instantiation of MicrosecondHistogram,
93// which causes linker errors for any target which includes histogram.h and not
94// histogram.cc
95void MicrosecondStopwatch::stop(ProcessClock::time_point end) {
96    const auto spent = end - startTime;
97    histogram.add(std::chrono::duration_cast<std::chrono::microseconds>(spent));
98}
99