From 7718a63b24cf8dc35758a5b9020acbf993dc2292 Mon Sep 17 00:00:00 2001 From: mutouyun Date: Wed, 21 Nov 2018 21:38:29 +0800 Subject: [PATCH] print spent time & performance --- src/circ_queue.h | 5 +- test/stopwatch.hpp | 109 +++++++++++++++++++++++++++++++++++++++ test/test_circ_queue.cpp | 24 +++++---- 3 files changed, 125 insertions(+), 13 deletions(-) create mode 100644 test/stopwatch.hpp diff --git a/src/circ_queue.h b/src/circ_queue.h index 4167308..1485503 100644 --- a/src/circ_queue.h +++ b/src/circ_queue.h @@ -62,10 +62,7 @@ public: auto st = begin() + id(cr_.load(std::memory_order_relaxed)); do { // check remain count of consumers - if (st->head_.load(std::memory_order_acquire)) { - std::this_thread::yield(); - } - else { + if (!st->head_.load(std::memory_order_acquire)) { st->head_.store(conn_count()); break; } diff --git a/test/stopwatch.hpp b/test/stopwatch.hpp new file mode 100644 index 0000000..1e96dcb --- /dev/null +++ b/test/stopwatch.hpp @@ -0,0 +1,109 @@ +/* + The Capo Library + Code covered by the MIT License + + Author: mutouyun (http://orzz.org) +*/ + +#pragma once + +#include // std::chrono +#include // std::array +#include // std::pair, std::declval +#include // size_t + +namespace capo { + +//////////////////////////////////////////////////////////////// +/// Stopwatch - can store multiple sets of time +//////////////////////////////////////////////////////////////// + +template +class stopwatch : public ClockT +{ + using base_t = ClockT; + + static_assert(CountN > 0, "The count must be greater than 0"); + +public: + using rep = typename ClockT::rep; + using period = typename ClockT::period; + using duration = typename ClockT::duration; + using time_point = typename ClockT::time_point; + +private: + using pair_t = std::pair; + + std::array points_; + bool is_stopped_ = true; + +public: + stopwatch(bool start_watch = false) + { + if (start_watch) start(); + } + +public: + bool is_stopped(void) const + { + return is_stopped_; + } + + template + bool is_paused(void) const + { + return (points_[N].second != points_[N].first); + } + + template + duration elapsed(void) + { + if (is_stopped()) + return duration::zero(); + else + if (is_paused()) + return (points_[N].second - points_[N].first); + else + return ClockT::now() - points_[N].first; + } + + template + auto elapsed(void) -> decltype(std::declval().count()) + { + return std::chrono::duration_cast(elapsed()).count(); + } + + template + void pause(void) + { + points_[N].second = ClockT::now(); + } + + template + void restart(void) + { + points_[N].second = points_[N].first = + ClockT::now() - (points_[N].second - points_[N].first); + } + + void start(void) + { + time_point now = ClockT::now(); + for (auto& pt : points_) + { + pt.second = pt.first = now - (pt.second - pt.first); + } + is_stopped_ = false; + } + + void stop(void) + { + for (auto& pt : points_) + { + pt.second = pt.first; + } + is_stopped_ = true; + } +}; + +} // namespace capo diff --git a/test/test_circ_queue.cpp b/test/test_circ_queue.cpp index 40a97f5..618d453 100644 --- a/test/test_circ_queue.cpp +++ b/test/test_circ_queue.cpp @@ -2,9 +2,11 @@ #include #include #include +#include #include "circ_queue.h" #include "test.h" +#include "stopwatch.hpp" namespace { @@ -32,8 +34,8 @@ void Unit::test_inst(void) { } void Unit::test_producer(void) { - cq__ = new cq_t; - std::thread consumers[3]; + ::new (cq__) cq_t; + std::thread consumers[1]; for (auto& c : consumers) { c = std::thread{[&c] { @@ -48,11 +50,8 @@ void Unit::test_producer(void) { do { while (cur != cq__->cursor()) { int d = *static_cast(cq__->get(cur)); -// std::cout << &c << ": cur = " << (int)cur << ", " << d << std::endl; - if (d < 0) { - return; - } - else QCOMPARE(d, i); + if (d < 0) return; + QCOMPARE(d, i); ++cur; ++i; } @@ -63,20 +62,27 @@ void Unit::test_producer(void) { while (cq__->conn_count() != std::extent::value) { std::this_thread::yield(); } + capo::stopwatch<> sw; + constexpr static int loops = 1000000; + std::cout << "start producer..." << std::endl; - for (int i = 0; i < 1000; ++i) { + sw.start(); + for (int i = 0; i < loops; ++i) { auto d = static_cast(cq__->acquire()); *d = i; cq__->commit(); } auto d = static_cast(cq__->acquire()); *d = -1; - std::cout << "put: quit..." << std::endl; cq__->commit(); for (auto& c : consumers) { c.join(); } + + auto ts = sw.elapsed(); + std::cout << "time spent : " << (ts / 1000) << " ms" << std::endl; + std::cout << "performance: " << (double(ts) / double(loops)) << " us/msg" << std::endl; } } // internal-linkage