Coverage Report

Created: 2025-07-06 13:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/builds/MusicScience37Projects/utility-libraries/cpp-stat-bench/include/stat_bench/stat/custom_stat_output.h
Line
Count
Source
1
/*
2
 * Copyright 2021 MusicScience37 (Kenta Kabashima)
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
/*!
17
 * \file
18
 * \brief Definition of CustomStatOutput class.
19
 */
20
#pragma once
21
22
#include <cstddef>
23
#include <cstdint>
24
#include <utility>
25
#include <vector>
26
27
#include "stat_bench/clock/duration.h"
28
#include "stat_bench/custom_output_name.h"
29
#include "stat_bench/stat/calc_stat.h"
30
#include "stat_bench/stat/statistics.h"
31
#include "stat_bench/stat_bench_exception.h"
32
33
namespace stat_bench {
34
namespace stat {
35
36
/*!
37
 * \brief Enumeration of types of analysis applied to custom outputs.
38
 */
39
enum class CustomOutputAnalysisType : std::uint8_t {
40
    mean,         //!< Mean per sample.
41
    rate_per_sec  //!< Rate per sec.
42
};
43
44
/*!
45
 * \brief Class of custom outputs with statistics.
46
 */
47
class CustomStatOutput {
48
public:
49
    /*!
50
     * \brief Constructor.
51
     *
52
     * \param[in] name Name.
53
     * \param[in] threads Number of threads.
54
     * \param[in] samples Number of samples (including warming_up_samples).
55
     * \param[in] warming_up_samples Number of samples for warming up. (They're
56
     * ignored.)
57
     * \param[in] iterations Number of iterations. \param[in]
58
     * analysis_type Type of analysis.
59
     */
60
    CustomStatOutput(CustomOutputName name, std::size_t threads,
61
        std::size_t samples, std::size_t warming_up_samples,
62
        std::size_t iterations, CustomOutputAnalysisType analysis_type)
63
528
        : name_(std::move(name)),
64
528
          threads_(threads),
65
528
          samples_(samples),
66
528
          warming_up_samples_(warming_up_samples),
67
528
          iterations_(iterations),
68
528
          analysis_type_(analysis_type) {
69
528
        if (samples <= warming_up_samples) {
70
0
            throw StatBenchException("Invalid number of samples.");
71
0
        }
72
528
        data_.reserve(threads_);
73
528
        const std::size_t used_samples = samples - warming_up_samples;
74
1.06k
        for (std::size_t i = 0; i < threads_; ++i) {
75
532
            data_.emplace_back(used_samples, 0.0);
76
532
        }
77
528
    }
78
79
    /*!
80
     * \brief Add a value.
81
     *
82
     * \param[in] thread_index Index of the thread.
83
     * \param[in] sample_index Index of the sample.
84
     * \param[in] val Value of the current iteration.
85
     */
86
781k
    void add(std::size_t thread_index, std::size_t sample_index, double val) {
87
781k
        if (sample_index < warming_up_samples_) {
88
61.1k
            return;
89
61.1k
        }
90
720k
        data_.at(thread_index).at(sample_index - warming_up_samples_) += val;
91
720k
    }
92
93
    /*!
94
     * \brief Preprocess data.
95
     *
96
     * \param[in] durations Durations.
97
     */
98
    void preprocess(
99
526
        const std::vector<std::vector<clock::Duration>>& durations) {
100
526
        const std::size_t used_samples = samples_ - warming_up_samples_;
101
1.05k
        for (std::size_t i = 0; i < threads_; ++i) {
102
121k
            for (std::size_t j = 0; j < used_samples; ++j) {
103
121k
                double& val = data_.at(i).at(j);
104
105
121k
                switch (analysis_type_) {
106
150
                case CustomOutputAnalysisType::mean:
107
150
                    val /= static_cast<double>(iterations_);
108
150
                    break;
109
120k
                case CustomOutputAnalysisType::rate_per_sec:
110
120k
                    val /= durations.at(i).at(j).seconds();
111
120k
                    break;
112
121k
                }
113
121k
            }
114
528
        }
115
526
    }
116
117
    /*!
118
     * \brief Calculate statistics.
119
     *
120
     * \return Statistics.
121
     */
122
526
    [[nodiscard]] auto stat() const -> Statistics { return calc_stat(data_); }
123
124
    /*!
125
     * \brief Get the name.
126
     *
127
     * \return Name.
128
     */
129
182
    [[nodiscard]] auto name() const noexcept -> const CustomOutputName& {
130
182
        return name_;
131
182
    }
132
133
    /*!
134
     * \brief Get data.
135
     *
136
     * \return Data.
137
     */
138
    [[nodiscard]] auto data() const noexcept
139
72
        -> const std::vector<std::vector<double>>& {
140
72
        return data_;
141
72
    }
142
143
private:
144
    //! Name.
145
    CustomOutputName name_;
146
147
    //! Data.
148
    std::vector<std::vector<double>> data_{};
149
150
    //! Number of threads.
151
    std::size_t threads_;
152
153
    //! Number of total samples.
154
    std::size_t samples_;
155
156
    //! Number of samples for warming up.
157
    std::size_t warming_up_samples_;
158
159
    //! Number of iterations.
160
    std::size_t iterations_;
161
162
    //! Type of analysis.
163
    CustomOutputAnalysisType analysis_type_;
164
};
165
166
}  // namespace stat
167
}  // namespace stat_bench