• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

4.25
/libs/full/performance_counters/src/server/statistics_counter.cpp
1
//  Copyright (c) 2007-2025 Hartmut Kaiser
2
//
3
//  SPDX-License-Identifier: BSL-1.0
4
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
5
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6

7
#include <hpx/config.hpp>
8
#include <hpx/async_distributed/continuation.hpp>
9
#include <hpx/components_base/agas_interface.hpp>
10
#include <hpx/modules/async_base.hpp>
11
#include <hpx/modules/errors.hpp>
12
#include <hpx/modules/functional.hpp>
13
#include <hpx/modules/runtime_local.hpp>
14
#include <hpx/modules/thread_support.hpp>
15
#include <hpx/performance_counters/counter_creators.hpp>
16
#include <hpx/performance_counters/counters.hpp>
17
#include <hpx/performance_counters/performance_counter.hpp>
18
#include <hpx/performance_counters/server/statistics_counter.hpp>
19
#include <hpx/runtime_components/derived_component_factory.hpp>
20

21
#include <boost/accumulators/accumulators.hpp>
22
#include <boost/accumulators/statistics/max.hpp>
23
#include <boost/accumulators/statistics/mean.hpp>
24
#include <boost/accumulators/statistics/min.hpp>
25
#include <boost/accumulators/statistics/rolling_mean.hpp>
26
#include <boost/accumulators/statistics/rolling_variance.hpp>
27
#include <boost/accumulators/statistics/stats.hpp>
28
#include <boost/accumulators/statistics/variance.hpp>
29

30
#include <hpx/statistics/rolling_max.hpp>
31
#include <hpx/statistics/rolling_min.hpp>
32

33
#if defined(HPX_MSVC)
34
#pragma warning(push)
35
#pragma warning(disable : 4244)
36
#endif
37
#include <boost/accumulators/statistics/median.hpp>
38
#if defined(HPX_MSVC)
39
#pragma warning(pop)
40
#endif
41

42
#include <boost/spirit/home/x3/char.hpp>
43
#include <boost/spirit/home/x3/core.hpp>
44
#include <boost/spirit/home/x3/numeric.hpp>
45
#include <boost/spirit/home/x3/operator.hpp>
46

47
#include <boost/version.hpp>
48

49
#include <cstddef>
50
#include <cstdint>
51
#include <mutex>
52
#include <string>
53
#include <vector>
54

55
#include <hpx/config/warnings_prefix.hpp>
56

57
///////////////////////////////////////////////////////////////////////////////
58
namespace hpx::performance_counters::server {
59

60
    ///////////////////////////////////////////////////////////////////////////
61
    namespace detail {
62
        template <typename Statistic>
63
        struct counter_type_from_statistic;
64

65
        template <>
66
        struct counter_type_from_statistic<boost::accumulators::tag::mean>
67
          : counter_type_from_statistic_base
68
        {
69
            using aggregating_tag = boost::accumulators::tag::mean;
70
            using accumulator_type =
71
                boost::accumulators::accumulator_set<double,
×
72
                    boost::accumulators::stats<aggregating_tag>>;
73

×
74
            counter_type_from_statistic(std::size_t /*parameter2*/) {}
75

×
76
            double get_value() override
77
            {
78
                return boost::accumulators::mean(accum_);
×
79
            }
80

81
            void add_value(double value) override
×
82
            {
83
                accum_(value);
×
84
            }
85

×
86
            bool need_reset() const override
87
            {
88
                return false;
89
            }
90

91
        private:
92
            accumulator_type accum_;
93
        };
94

95
        template <>
96
        struct counter_type_from_statistic<boost::accumulators::tag::variance>
97
          : counter_type_from_statistic_base
98
        {
99
            using aggregating_tag = boost::accumulators::tag::variance;
100
            using accumulator_type =
101
                boost::accumulators::accumulator_set<double,
×
102
                    boost::accumulators::stats<aggregating_tag>>;
103

×
104
            counter_type_from_statistic(std::size_t /*parameter2*/) {}
105

×
106
            double get_value() override
107
            {
108
                return sqrt(boost::accumulators::variance(accum_));
×
109
            }
110

×
111
            void add_value(double value) override
×
112
            {
113
                accum_(value);
×
114
            }
115

×
116
            bool need_reset() const override
117
            {
118
                return false;
119
            }
120

121
        private:
122
            accumulator_type accum_;
123
        };
124

125
        template <>
126
        struct counter_type_from_statistic<boost::accumulators::tag::median>
127
          : counter_type_from_statistic_base
128
        {
129
            using aggregating_tag = boost::accumulators::tag::median;
130
            using aggregating_type_tag =
131
                boost::accumulators::with_p_square_quantile;
132
            using accumulator_type =
133
                boost::accumulators::accumulator_set<double,
134
                    boost::accumulators::stats<aggregating_tag(
×
135
                        aggregating_type_tag)>>;
136

×
137
            counter_type_from_statistic(std::size_t /*parameter2*/) {}
138

×
139
            double get_value() override
140
            {
141
                return boost::accumulators::median(accum_);
×
142
            }
143

×
144
            void add_value(double value) override
×
145
            {
146
                accum_(value);
×
147
            }
148

×
149
            bool need_reset() const override
150
            {
151
                return false;
152
            }
153

154
        private:
155
            accumulator_type accum_;
156
        };
157

158
        template <>
159
        struct counter_type_from_statistic<
160
            boost::accumulators::tag::rolling_mean>
161
          : counter_type_from_statistic_base
162
        {
163
            using aggregating_tag = boost::accumulators::tag::rolling_mean;
164
            using accumulator_type =
165
                boost::accumulators::accumulator_set<double,
×
166
                    boost::accumulators::stats<aggregating_tag>>;
×
167

×
168
            counter_type_from_statistic(std::size_t parameter2)
169
              : accum_(boost::accumulators::tag::rolling_window::window_size =
×
170
                           parameter2)
171
            {
×
172
                if (parameter2 == 0)
173
                {
174
                    HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
175
                        "counter_type_from_statistic<Statistic>",
×
176
                        "base rolling window size is specified to be zero");
177
                }
×
178
            }
179

×
180
            double get_value() override
181
            {
182
                return boost::accumulators::rolling_mean(accum_);
×
183
            }
184

×
185
            void add_value(double value) override
×
186
            {
187
                accum_(value);
×
188
            }
189

×
190
            bool need_reset() const override
191
            {
192
                return false;
193
            }
194

195
        private:
196
            accumulator_type accum_;
197
        };
198

199
        template <>
200
        struct counter_type_from_statistic<
201
            boost::accumulators::tag::rolling_variance>
202
          : counter_type_from_statistic_base
203
        {
204
            using aggregating_tag = boost::accumulators::tag::rolling_variance;
205
            using accumulator_type =
206
                boost::accumulators::accumulator_set<double,
×
207
                    boost::accumulators::stats<aggregating_tag>>;
×
208

×
209
            counter_type_from_statistic(std::size_t parameter2)
210
              : accum_(boost::accumulators::tag::rolling_window::window_size =
×
211
                           parameter2)
212
            {
×
213
                if (parameter2 == 0)
214
                {
215
                    HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
216
                        "counter_type_from_statistic<Statistic>",
×
217
                        "base rolling window size is specified to be zero");
218
                }
×
219
            }
220

×
221
            double get_value() override
222
            {
223
                return sqrt(boost::accumulators::rolling_variance(accum_));
×
224
            }
225

×
226
            void add_value(double value) override
×
227
            {
228
                accum_(value);
×
229
            }
230

×
231
            bool need_reset() const override
232
            {
233
                return false;
234
            }
235

236
        private:
237
            accumulator_type accum_;
238
        };
239

240
        template <>
241
        struct counter_type_from_statistic<boost::accumulators::tag::max>
242
          : counter_type_from_statistic_base
243
        {
244
            using aggregating_tag = boost::accumulators::tag::max;
245
            using accumulator_type =
246
                boost::accumulators::accumulator_set<double,
×
247
                    boost::accumulators::stats<aggregating_tag>>;
248

×
249
            counter_type_from_statistic(std::size_t /*parameter2*/) {}
250

×
251
            double get_value() override
252
            {
253
                return (boost::accumulators::max) (accum_);
×
254
            }
255

256
            void add_value(double value) override
×
257
            {
258
                accum_(value);
×
259
            }
260

×
261
            bool need_reset() const override
262
            {
263
                return true;
264
            }
265

266
        private:
267
            accumulator_type accum_;
268
        };
269

270
        template <>
271
        struct counter_type_from_statistic<boost::accumulators::tag::min>
272
          : counter_type_from_statistic_base
273
        {
274
            using aggregating_tag = boost::accumulators::tag::min;
275
            using accumulator_type =
276
                boost::accumulators::accumulator_set<double,
×
277
                    boost::accumulators::stats<aggregating_tag>>;
278

×
279
            counter_type_from_statistic(std::size_t /*parameter2*/) {}
280

×
281
            double get_value() override
282
            {
283
                return (boost::accumulators::min) (accum_);
×
284
            }
285

286
            void add_value(double value) override
×
287
            {
288
                accum_(value);
×
289
            }
290

×
291
            bool need_reset() const override
292
            {
293
                return true;
294
            }
295

296
        private:
297
            accumulator_type accum_;
298
        };
299

300
        template <>
301
        struct counter_type_from_statistic<hpx::util::tag::rolling_min>
302
          : counter_type_from_statistic_base
303
        {
304
            using aggregating_tag = hpx::util::tag::rolling_min;
305
            using accumulator_type =
306
                boost::accumulators::accumulator_set<double,
×
307
                    boost::accumulators::stats<aggregating_tag>>;
×
308

×
309
            counter_type_from_statistic(std::size_t parameter2)
310
              : accum_(boost::accumulators::tag::rolling_window::window_size =
×
311
                           parameter2)
312
            {
×
313
                if (parameter2 == 0)
314
                {
315
                    HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
316
                        "counter_type_from_statistic<Statistic>",
×
317
                        "base rolling window size is specified to be zero");
318
                }
×
319
            }
320

×
321
            double get_value() override
322
            {
323
                return hpx::util::rolling_min(accum_);
×
324
            }
325

326
            void add_value(double value) override
×
327
            {
328
                accum_(value);
×
329
            }
330

×
331
            bool need_reset() const override
332
            {
333
                return false;
334
            }
335

336
        private:
337
            accumulator_type accum_;
338
        };
339

340
        template <>
341
        struct counter_type_from_statistic<hpx::util::tag::rolling_max>
342
          : counter_type_from_statistic_base
343
        {
344
            using aggregating_tag = hpx::util::tag::rolling_max;
345
            using accumulator_type =
346
                boost::accumulators::accumulator_set<double,
×
347
                    boost::accumulators::stats<aggregating_tag>>;
×
348

×
349
            counter_type_from_statistic(std::size_t parameter2)
350
              : accum_(boost::accumulators::tag::rolling_window::window_size =
×
351
                           parameter2)
352
            {
×
353
                if (parameter2 == 0)
354
                {
355
                    HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
356
                        "counter_type_from_statistic<Statistic>",
×
357
                        "base rolling window size is specified to be zero");
358
                }
×
359
            }
360

×
361
            double get_value() override
362
            {
363
                return hpx::util::rolling_max(accum_);
×
364
            }
365

366
            void add_value(double value) override
×
367
            {
368
                accum_(value);
×
369
            }
370

×
371
            bool need_reset() const override
372
            {
373
                return false;
374
            }
375

376
        private:
377
            accumulator_type accum_;
378
        };
379
    }    // namespace detail
380

×
381
    ///////////////////////////////////////////////////////////////////////////
×
382
    template <typename Statistic>
×
383
    statistics_counter<Statistic>::statistics_counter()
×
384
      : has_prev_value_(false)
×
385
      , parameter1_(0)
386
      , parameter2_(0)
×
387
      , reset_base_counter_(false)
388
    {
389
    }
×
390

391
    template <typename Statistic>
392
    statistics_counter<Statistic>::statistics_counter(counter_info const& info,
393
        std::string const& base_counter_name, std::size_t parameter1,
×
394
        std::size_t parameter2, bool reset_base_counter)
395
      : base_type_holder(info)
×
396
      , timer_(hpx::bind_front(&statistics_counter::evaluate, this_()),
×
397
            hpx::bind_front(&statistics_counter::on_terminate, this_()),
×
398
            1000 * parameter1, info.fullname_, true)
×
399
      , base_counter_name_(ensure_counter_prefix(base_counter_name))
×
400
      , value_(new detail::counter_type_from_statistic<Statistic>(parameter2))
×
401
      , has_prev_value_(false)
×
402
      , parameter1_(parameter1)
403
      , parameter2_(parameter2)
×
404
      , reset_base_counter_(reset_base_counter)
405
    {
×
406
        if (parameter1 == 0)
407
        {
408
            HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
409
                "statistics_counter<Statistic>::statistics_counter",
410
                "base interval is specified to be zero");
×
411
        }
412

×
413
        if (info.type_ != counter_type::aggregating)
414
        {
415
            HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
416
                "statistics_counter<Statistic>::statistics_counter",
417
                "unexpected counter type specified");
418
        }
×
419

×
420
        // make sure this counter starts collecting data
421
        statistics_counter<Statistic>::start();
422
    }
423

×
424
    template <typename Statistic>
425
    hpx::performance_counters::counter_value
×
426
    statistics_counter<Statistic>::get_counter_value(bool reset)
427
    {
428
        std::lock_guard<mutex_type> l(mtx_);
429

×
430
        hpx::performance_counters::counter_value value;
×
431

×
432
        prev_value_.value_ = static_cast<std::int64_t>(value_->get_value());
×
433
        prev_value_.status_ = counter_status::new_data;
×
434
        prev_value_.time_ = static_cast<std::int64_t>(hpx::get_system_uptime());
435
        prev_value_.count_ = ++invocation_count_;
×
436
        has_prev_value_ = true;
437

×
438
        value = prev_value_;    // return value
439

×
440
        if (reset || value_->need_reset())
441
        {
×
442
            value_.reset(new detail::counter_type_from_statistic<Statistic>(
443
                parameter2_));    // reset accumulator
444
            value_->add_value(static_cast<double>(prev_value_.value_));
445
            // start off with last base value
×
446
        }
447

448
        return value;
449
    }
×
450

451
    template <typename Statistic>
452
    bool statistics_counter<Statistic>::evaluate()
453
    {
×
454
        // gather current base value
455
        counter_value base_value;
456
        if (!evaluate_base_counter(base_value))
457
            return false;
458

459
        // simply average the measured base counter values since it got queried
×
460
        // for the last time
×
461
        counter_value value;
462
        if (base_value.scaling_ != prev_value_.scaling_ ||
463
            base_value.scale_inverse_ != prev_value_.scale_inverse_)
×
464
        {
465
            // not supported right now
466
            HPX_THROW_EXCEPTION(hpx::error::not_implemented,
467
                "statistics_counter<Statistic>::evaluate",
468
                "base counter should keep scaling constant over time");
469
            return false;
470
        }
471
        else
×
472
        {
×
473
            // accumulate new value
474
            std::lock_guard<mutex_type> l(mtx_);
×
475
            value_->add_value(static_cast<double>(base_value.value_));
476
        }
477
        return true;
478
    }
×
479

480
    template <typename Statistic>
481
    bool statistics_counter<Statistic>::ensure_base_counter()
482
    {
×
483
        // lock here to avoid checking out multiple reference counted GIDs
484
        // from AGAS. This
485
        std::unique_lock<mutex_type> l(mtx_);
486

487
        if (!base_counter_id_)
488
        {
×
489
            // get or create the base counter
490
            error_code ec(throwmode::lightweight);
491
            hpx::id_type base_counter_id;
492
            {
×
493
                // We need to unlock the lock here since get_counter might suspend
494
                unlock_guard<std::unique_lock<mutex_type>> unlock(l);
495
                base_counter_id = get_counter(base_counter_name_, ec);
496
            }
497

498
            // After reacquiring the lock, we need to check again if base_counter_id_
499
            // hasn't been set yet
500
            if (!base_counter_id_)
501
            {
502
                base_counter_id_ = base_counter_id;
503
            }
504
            else
505
            {
506
                // If it was set already by a different thread, return true.
507
                return true;
×
508
            }
509

510
            if (HPX_UNLIKELY(ec || !base_counter_id_))
×
511
            {
512
                // base counter could not be retrieved
513
                HPX_THROW_EXCEPTION(hpx::error::bad_parameter,
514
                    "statistics_counter<Statistic>::evaluate_base_counter",
515
                    "could not get or create performance counter: '{}'",
516
                    base_counter_name_);
517
                return false;
518
            }
519
        }
520

521
        return true;
522
    }
×
523

524
    template <typename Statistic>
525
    bool statistics_counter<Statistic>::evaluate_base_counter(
526
        counter_value& value)
×
527
    {
528
        // query the actual value
529
        if (!base_counter_id_ && !ensure_base_counter())
×
530
            return false;
×
531

532
        performance_counters::performance_counter c(base_counter_id_);
×
533
        value = c.get_counter_value(launch::sync, reset_base_counter_);
534

×
535
        if (!has_prev_value_)
×
536
        {
537
            has_prev_value_ = true;
538
            prev_value_ = value;
539
        }
540

541
        return true;
542
    }
543

544
    ///////////////////////////////////////////////////////////////////////////
545
    // Start and stop this counter. We dispatch the calls to the base counter
×
546
    // and control our own interval_timer.
547
    template <typename Statistic>
×
548
    bool statistics_counter<Statistic>::start()
549
    {
550
        if (!timer_.is_started())
×
551
        {
552
            // start base counter
553
            if (!base_counter_id_ && !ensure_base_counter())
×
554
                return false;
×
555

×
556
            performance_counters::performance_counter c(base_counter_id_);
557
            bool result = c.start(launch::sync);
558
            if (result)
559
            {
×
560
                // acquire the current value of the base counter
561
                counter_value base_value;
×
562
                if (evaluate_base_counter(base_value))
×
563
                {
×
564
                    std::lock_guard<mutex_type> l(mtx_);
565
                    value_->add_value(static_cast<double>(base_value.value_));
566
                    prev_value_ = base_value;
567
                }
568

569
                // start timer
570
                timer_.start();
571
            }
572
            else
573
            {
574
                // start timer even if base counter does not support being
575
                // start/stop operations
576
                timer_.start(true);
577
            }
578
            return result;
579
        }
580
        return false;
581
    }
×
582

583
    template <typename Statistic>
×
584
    bool statistics_counter<Statistic>::stop()
585
    {
586
        if (timer_.is_started())
587
        {
×
588
            timer_.stop();
589

590
            if (!base_counter_id_ && !ensure_base_counter())
×
591
                return false;
×
592

593
            performance_counters::performance_counter c(base_counter_id_);
594
            return c.stop(launch::sync);
595
        }
596
        return false;
597
    }
×
598

599
    template <typename Statistic>
×
600
    void statistics_counter<Statistic>::reset_counter_value()
601
    {
602
        std::lock_guard<mutex_type> l(mtx_);
603

×
604
        // reset accumulator
605
        value_.reset(
606
            new detail::counter_type_from_statistic<Statistic>(parameter2_));
×
607

×
608
        // start off with last base value
609
        value_->add_value(static_cast<double>(prev_value_.value_));
610
    }
×
611

612
    template <typename Statistic>
×
613
    void statistics_counter<Statistic>::on_terminate()
614
    {
615
    }
×
616

617
    template <typename Statistic>
618
    void statistics_counter<Statistic>::finalize()
619
    {
×
620
        base_performance_counter::finalize();
621
        base_type::finalize();
622
    }
×
623

624
    template <typename Statistic>
625
    naming::address statistics_counter<Statistic>::get_current_address() const
626
    {
627
        return naming::address(
×
628
            naming::get_gid_from_locality_id(agas::get_locality_id()),
629
            components::get_component_type<statistics_counter>(),
630
            const_cast<statistics_counter*>(this));
631
    }
632
}    // namespace hpx::performance_counters::server
633

634
///////////////////////////////////////////////////////////////////////////////
635
template class HPX_EXPORT hpx::performance_counters::server::statistics_counter<
636
    boost::accumulators::tag::mean>;
637
template class HPX_EXPORT hpx::performance_counters::server::statistics_counter<
638
    boost::accumulators::tag::variance>;
639
template class HPX_EXPORT hpx::performance_counters::server::statistics_counter<
640
    boost::accumulators::tag::rolling_variance>;
641
template class HPX_EXPORT hpx::performance_counters::server::statistics_counter<
642
    boost::accumulators::tag::median>;
643
template class HPX_EXPORT hpx::performance_counters::server::statistics_counter<
644
    boost::accumulators::tag::rolling_mean>;
645
template class HPX_EXPORT hpx::performance_counters::server::statistics_counter<
646
    boost::accumulators::tag::max>;
647
template class HPX_EXPORT hpx::performance_counters::server::statistics_counter<
648
    boost::accumulators::tag::min>;
649
template class HPX_EXPORT hpx::performance_counters::server::statistics_counter<
650
    hpx::util::tag::rolling_min>;
651
template class HPX_EXPORT hpx::performance_counters::server::statistics_counter<
652
    hpx::util::tag::rolling_max>;
653

654
///////////////////////////////////////////////////////////////////////////////
655
// Average
656
using average_count_counter_type =
657
    hpx::components::component<hpx::performance_counters::server::
×
658
            statistics_counter<boost::accumulators::tag::mean>>;
659

660
HPX_REGISTER_DERIVED_COMPONENT_FACTORY(average_count_counter_type,
32✔
661
    average_count_counter, "base_performance_counter",
662
    hpx::components::factory_state::enabled)
663
HPX_DEFINE_GET_COMPONENT_TYPE(average_count_counter_type::wrapped_type)
664

665
///////////////////////////////////////////////////////////////////////////////
666
// Rolling variance
667
using rolling_variance_count_counter_type =
668
    hpx::components::component<hpx::performance_counters::server::
×
669
            statistics_counter<boost::accumulators::tag::rolling_variance>>;
670

671
HPX_REGISTER_DERIVED_COMPONENT_FACTORY(rolling_variance_count_counter_type,
32✔
672
    rolling_variance_count_counter, "base_performance_counter",
673
    hpx::components::factory_state::enabled)
674
HPX_DEFINE_GET_COMPONENT_TYPE(rolling_variance_count_counter_type::wrapped_type)
675

676
///////////////////////////////////////////////////////////////////////////////
677
// Variance
678
using variance_count_counter_type =
679
    hpx::components::component<hpx::performance_counters::server::
×
680
            statistics_counter<boost::accumulators::tag::variance>>;
681

682
HPX_REGISTER_DERIVED_COMPONENT_FACTORY(variance_count_counter_type,
32✔
683
    variance_count_counter, "base_performance_counter",
684
    hpx::components::factory_state::enabled)
685
HPX_DEFINE_GET_COMPONENT_TYPE(variance_count_counter_type::wrapped_type)
686

687
///////////////////////////////////////////////////////////////////////////////
688
// Rolling average
689
using rolling_mean_count_counter_type =
690
    hpx::components::component<hpx::performance_counters::server::
×
691
            statistics_counter<boost::accumulators::tag::rolling_mean>>;
692

693
HPX_REGISTER_DERIVED_COMPONENT_FACTORY(rolling_mean_count_counter_type,
32✔
694
    rolling_mean_count_counter, "base_performance_counter",
695
    hpx::components::factory_state::enabled)
696
HPX_DEFINE_GET_COMPONENT_TYPE(rolling_mean_count_counter_type::wrapped_type)
697

698
///////////////////////////////////////////////////////////////////////////////
699
// Median
700
using median_count_counter_type =
701
    hpx::components::component<hpx::performance_counters::server::
×
702
            statistics_counter<boost::accumulators::tag::median>>;
703

704
HPX_REGISTER_DERIVED_COMPONENT_FACTORY(median_count_counter_type,
32✔
705
    median_count_counter, "base_performance_counter",
706
    hpx::components::factory_state::enabled)
707
HPX_DEFINE_GET_COMPONENT_TYPE(median_count_counter_type::wrapped_type)
708

709
///////////////////////////////////////////////////////////////////////////////
710
// Max
711
using max_count_counter_type =
712
    hpx::components::component<hpx::performance_counters::server::
×
713
            statistics_counter<boost::accumulators::tag::max>>;
714

715
HPX_REGISTER_DERIVED_COMPONENT_FACTORY(max_count_counter_type,
32✔
716
    max_count_counter, "base_performance_counter",
717
    hpx::components::factory_state::enabled)
718
HPX_DEFINE_GET_COMPONENT_TYPE(max_count_counter_type::wrapped_type)
719

720
///////////////////////////////////////////////////////////////////////////////
721
// Min
722
using min_count_counter_type =
723
    hpx::components::component<hpx::performance_counters::server::
×
724
            statistics_counter<boost::accumulators::tag::min>>;
725

726
HPX_REGISTER_DERIVED_COMPONENT_FACTORY(min_count_counter_type,
32✔
727
    min_count_counter, "base_performance_counter",
728
    hpx::components::factory_state::enabled)
729
HPX_DEFINE_GET_COMPONENT_TYPE(min_count_counter_type::wrapped_type)
730

731
///////////////////////////////////////////////////////////////////////////////
732
// Rolling min
733
using rolling_min_count_counter_type =
734
    hpx::components::component<hpx::performance_counters::server::
×
735
            statistics_counter<hpx::util::tag::rolling_min>>;
736

737
HPX_REGISTER_DERIVED_COMPONENT_FACTORY(rolling_min_count_counter_type,
32✔
738
    rolling_min_count_counter, "base_performance_counter",
739
    hpx::components::factory_state::enabled)
740
HPX_DEFINE_GET_COMPONENT_TYPE(rolling_min_count_counter_type::wrapped_type)
741

742
///////////////////////////////////////////////////////////////////////////////
743
// Rolling max
744
using rolling_max_count_counter_type =
745
    hpx::components::component<hpx::performance_counters::server::
×
746
            statistics_counter<hpx::util::tag::rolling_max>>;
747

748
HPX_REGISTER_DERIVED_COMPONENT_FACTORY(rolling_max_count_counter_type,
32✔
749
    rolling_max_count_counter, "base_performance_counter",
750
    hpx::components::factory_state::enabled)
751
HPX_DEFINE_GET_COMPONENT_TYPE(rolling_max_count_counter_type::wrapped_type)
752

753
///////////////////////////////////////////////////////////////////////////////
754
namespace hpx::performance_counters::detail {
×
755

756
    /// Creation function for aggregating performance counters to be registered
757
    /// with the counter types.
×
758
    naming::gid_type statistics_counter_creator(
759
        counter_info const& info, error_code& ec)
760
    {
761
        if (info.type_ != counter_type::aggregating)
762
        {
×
763
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
764
                "statistics_counter_creator", "invalid counter type requested");
765
            return naming::invalid_gid;
766
        }
×
767

768
        counter_path_elements paths;
×
769
        get_counter_path_elements(info.fullname_, paths, ec);
770
        if (ec)
771
            return naming::invalid_gid;
772

773
        if (!paths.parentinstance_is_basename_)
774
        {
775
            HPX_THROWS_IF(ec, hpx::error::bad_parameter,
776
                "statistics_counter_creator",
×
777
                "invalid aggregate counter "
×
778
                "name (instance name must be valid base counter name)");
779
            return naming::invalid_gid;
780
        }
×
781

×
782
        std::string base_name;
783
        get_counter_name(paths.parentinstancename_, base_name, ec);
784
        if (ec)
785
            return naming::invalid_gid;
×
786

×
787
        std::vector<std::size_t> parameters;
788
        if (!paths.parameters_.empty())
×
789
        {
790
            // try to interpret the additional parameters
791
            namespace x3 = boost::spirit::x3;
792
            if (!x3::parse(paths.parameters_.begin(), paths.parameters_.end(),
793
                    x3::uint_ % ',', parameters))
794
            {
795
                HPX_THROWS_IF(ec, hpx::error::bad_parameter,
×
796
                    "statistics_counter_creator",
797
                    "invalid parameter specification format for "
×
798
                    "this counter: {}",
799
                    paths.parameters_);
×
800
                return naming::invalid_gid;
801
            }
802
            if (paths.countername_.find("rolling") != std::string::npos)
803
            {
804
                if (parameters.size() > 3)
805
                {
806
                    HPX_THROWS_IF(ec, hpx::error::bad_parameter,
807
                        "statistics_counter_creator",
×
808
                        "too many parameter specifications for "
809
                        "this counter: {}",
×
810
                        paths.parameters_);
811
                    return naming::invalid_gid;
812
                }
813
            }
814
            else if (parameters.size() > 2)
815
            {
816
                HPX_THROWS_IF(ec, hpx::error::bad_parameter,
817
                    "statistics_counter_creator",
×
818
                    "too many parameter specifications for "
819
                    "this counter: {}",
×
820
                    paths.parameters_);
×
821
                return naming::invalid_gid;
×
822
            }
823
        }
824
        else if (paths.countername_.find("rolling") != std::string::npos)
825
        {
×
826
            parameters.push_back(1000);    // sample interval
×
827
            parameters.push_back(10);      // rolling window
828
            parameters.push_back(0);       // don't reset underlying counter
×
829
        }
×
830
        else
831
        {
832
            parameters.push_back(1000);    // sample interval
833
            parameters.push_back(0);       // don't reset underlying counter
×
834
        }
835

836
        return create_statistics_counter(info, base_name, parameters, ec);
837
    }
838
}    // namespace hpx::performance_counters::detail
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc