C++實(shí)現(xiàn)統(tǒng)計(jì)代碼運(yùn)行時(shí)間的示例詳解
本來(lái)想自己寫的,一看github上面都有就不再重復(fù)造輪子了。github上的項(xiàng)目如下:
- StopWatch 純標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn):使用std::chrono::high_resolution_clock,其實(shí)就是std::chrono::steady_clock的別名。
- StopWatch 類似C#的實(shí)現(xiàn):和C#的StopWatch比較像,在Windows下使用的是QueryPerformanceCounter系統(tǒng)API,其它系統(tǒng)下使用std::chrono::steady_clock。
純標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)
第一種純標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)的Stopwatch.hpp內(nèi)容如下:
// Copyright Ingo Proff 2017.
// https://github.com/CrikeeIP/Stopwatch
// Distributed under the MIT Software License (X11 license).
// (See accompanying file LICENSE)
#pragma once
#include <vector>
#include <string>
#include <chrono>
namespace stopwatch{
class Stopwatch{
public:
enum TimeFormat{ NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS };
Stopwatch(): start_time(), laps({}) {
start();
}
void start(){
start_time = std::chrono::high_resolution_clock::now();
laps = {start_time};
}
template<TimeFormat fmt = TimeFormat::MILLISECONDS>
std::uint64_t lap(){
const auto t = std::chrono::high_resolution_clock::now();
const auto last_r = laps.back();
laps.push_back( t );
return ticks<fmt>(last_r, t);
}
template<TimeFormat fmt = TimeFormat::MILLISECONDS>
std::uint64_t elapsed(){
const auto end_time = std::chrono::high_resolution_clock::now();
return ticks<fmt>(start_time, end_time);
}
template<TimeFormat fmt_total = TimeFormat::MILLISECONDS, TimeFormat fmt_lap = fmt_total>
std::pair<std::uint64_t, std::vector<std::uint64_t>> elapsed_laps(){
std::vector<std::uint64_t> lap_times;
lap_times.reserve(laps.size()-1);
for( std::size_t idx = 0; idx <= laps.size()-2; idx++){
const auto lap_end = laps[idx+1];
const auto lap_start = laps[idx];
lap_times.push_back( ticks<fmt_lap>(lap_start, lap_end) );
}
return { ticks<fmt_total>(start_time, laps.back()), lap_times };
}
private:
typedef std::chrono::time_point<std::chrono::high_resolution_clock> time_pt;
time_pt start_time;
std::vector<time_pt> laps;
template<TimeFormat fmt = TimeFormat::MILLISECONDS>
static std::uint64_t ticks( const time_pt& start_time, const time_pt& end_time){
const auto duration = end_time - start_time;
const std::uint64_t ns_count = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
switch(fmt){
case TimeFormat::NANOSECONDS:
{
return ns_count;
}
case TimeFormat::MICROSECONDS:
{
std::uint64_t up = ((ns_count/100)%10 >= 5) ? 1 : 0;
const auto mus_count = (ns_count /1000) + up;
return mus_count;
}
case TimeFormat::MILLISECONDS:
{
std::uint64_t up = ((ns_count/100000)%10 >= 5) ? 1 : 0;
const auto ms_count = (ns_count /1000000) + up;
return ms_count;
}
case TimeFormat::SECONDS:
{
std::uint64_t up = ((ns_count/100000000)%10 >= 5) ? 1 : 0;
const auto s_count = (ns_count /1000000000) + up;
return s_count;
}
}
}
};
constexpr Stopwatch::TimeFormat ns = Stopwatch::TimeFormat::NANOSECONDS;
constexpr Stopwatch::TimeFormat mus = Stopwatch::TimeFormat::MICROSECONDS;
constexpr Stopwatch::TimeFormat ms = Stopwatch::TimeFormat::MILLISECONDS;
constexpr Stopwatch::TimeFormat s = Stopwatch::TimeFormat::SECONDS;
constexpr Stopwatch::TimeFormat nanoseconds = Stopwatch::TimeFormat::NANOSECONDS;
constexpr Stopwatch::TimeFormat microseconds = Stopwatch::TimeFormat::MICROSECONDS;
constexpr Stopwatch::TimeFormat milliseconds = Stopwatch::TimeFormat::MILLISECONDS;
constexpr Stopwatch::TimeFormat seconds = Stopwatch::TimeFormat::SECONDS;
std::string show_times( const std::vector<std::uint64_t>& times ){
std::string result("{");
for( const auto& t : times ){
result += std::to_string(t) + ",";
}
result.back() = static_cast<char>('}');
return result;
}
}
使用示例如下:
//創(chuàng)建一個(gè)stopwatch sw::Stopwatch my_watch; my_watch.start(); //Do something time-consuming here... //納秒 std::uint64_t elapsed_ns = my_watch.elapsed<sw::ns>(); //微秒 std::uint64_t elapsed_mus = my_watch.elapsed<sw::mus>(); //毫秒 std::uint64_t elapsed_ms = my_watch.elapsed(); //秒 std::uint64_t elapsed_s = my_watch.elapsed<sw::s>();
類似C#的實(shí)現(xiàn)
第二種類似C#的實(shí)現(xiàn),StopWatch.h代碼如下:
#ifndef __STOPWATCH_H__
#define __STOPWATCH_H__
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(WIN32)
#include <Windows.h>
#else
#include <chrono>
#endif
class StopWatch
{
public:
StopWatch();
~StopWatch();
//開啟計(jì)時(shí)
void Start();
//暫停計(jì)時(shí)
void Stop();
//重新計(jì)時(shí)
void ReStart();
//微秒
double Elapsed();
//毫秒
double ElapsedMS();
//秒
double ElapsedSecond();
private:
long long elapsed_;
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(WIN32)
LARGE_INTEGER start_;
LARGE_INTEGER stop_;
LARGE_INTEGER frequency_;
#else
typedef std::chrono::high_resolution_clock Clock;
typedef std::chrono::microseconds MicroSeconds;
std::chrono::steady_clock::time_point start_;
std::chrono::steady_clock::time_point stop_;
#endif
};
#endif // __STOPWATCH_H__
StopWatch.cpp代碼如下:
#include "StopWatch.h"
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(WIN32)
StopWatch::StopWatch():elapsed_(0)
{
elapsed_ = 0;
start_.QuadPart = 0;
stop_.QuadPart = 0;
QueryPerformanceFrequency(&frequency_);
}
#else
StopWatch::StopWatch():elapsed_(0),start_(MicroSeconds::zero()),stop_(MicroSeconds::zero())
{
}
#endif
StopWatch::~StopWatch()
{
}
void StopWatch::Start()
{
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(WIN32)
QueryPerformanceCounter(&start_);
#else
start_ = Clock::now();
#endif
}
void StopWatch::Stop()
{
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(WIN32)
QueryPerformanceCounter(&stop_);
elapsed_ += (stop_.QuadPart - start_.QuadPart) * 1000000 / frequency_.QuadPart;
#else
stop_ = Clock::now();
elapsed_ = std::chrono::duration_cast<MicroSeconds>(stop_ - start_).count();
#endif
}
void StopWatch::ReStart()
{
elapsed_ = 0;
Start();
}
double StopWatch::Elapsed()
{
return static_cast<double>(elapsed_);
}
double StopWatch::ElapsedMS()
{
return elapsed_ / 1000.0;
}
double StopWatch::ElapsedSecond()
{
return elapsed_ / 1000000.0;
}
使用示例如下(和C#比較像):
StopWatch sw; sw.Start(); //Do something time-consuming here... sw.Stop(); std::cout << "運(yùn)行時(shí)間:" << sw.ElapsedMS() << "毫秒" << std::endl;
總結(jié)
- 如果有代碼潔癖的話就使用第一種,純標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)、功能全面、使用方法偏向傳統(tǒng)C++。
- 如果不介意使用系統(tǒng)API的話就使用第二種,功能簡(jiǎn)單、使用方法偏向傳統(tǒng)C#。
到此這篇關(guān)于C++實(shí)現(xiàn)統(tǒng)計(jì)代碼運(yùn)行時(shí)間的示例詳解的文章就介紹到這了,更多相關(guān)C++統(tǒng)計(jì)代碼運(yùn)行時(shí)間內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
VSCode配置C/C++并添加非工作區(qū)頭文件的方法
這篇文章主要介紹了VSCode配置C/C++并添加非工作區(qū)頭文件的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
深入探索C++中stack和queue的底層實(shí)現(xiàn)
這篇文章主要介紹了C++中的stack和dequeue的底層實(shí)現(xiàn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09
基于C++的農(nóng)夫過(guò)河問(wèn)題算法設(shè)計(jì)與實(shí)現(xiàn)方法
這篇文章主要介紹了基于C++的農(nóng)夫過(guò)河問(wèn)題算法設(shè)計(jì)與實(shí)現(xiàn)方法,簡(jiǎn)單描述了農(nóng)夫過(guò)河問(wèn)題,并結(jié)合實(shí)例形式詳細(xì)分析了基于C++實(shí)現(xiàn)農(nóng)夫過(guò)河問(wèn)題的相關(guān)算法實(shí)現(xiàn)步驟與操作技巧,需要的朋友可以參考下2017-09-09
C++中vector容器的注意事項(xiàng)總結(jié)
在c++中,vector是一個(gè)十分有用的容器,下面這篇文章主要給大家介紹了關(guān)于C++中vector容器的注意事項(xiàng),文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-12-12

