首页 > 编程语言 >C++统计代码运行时间

C++统计代码运行时间

时间:2023-05-05 16:24:01浏览次数:48  
标签:std C++ elapsed 代码运行 StopWatch time Stopwatch TimeFormat 统计

本来想自己写的,一看github上面都有就不再重复造轮子了。github上的项目如下:

  • StopWatch 纯标准库实现:使用std::chrono::high_resolution_clock,其实就是std::chrono::steady_clock的别名。
  • StopWatch 类似C#的实现:和C#的StopWatch比较像,在Windows下使用的是QueryPerformanceCounter系统API,其它系统下使用std::chrono::steady_clock

纯标准库实现

第一种纯标准库实现的Stopwatch.hpp内容如下:

// 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;
}

}

使用示例如下:

//创建一个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#的实现

第二种类似C#的实现,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();

	//开启计时
	void Start();

	//暂停计时
	void Stop();

	//重新计时
	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 << "运行时间:" << sw.ElapsedMS() << "毫秒" << std::endl;

总结

  • 如果有代码洁癖的话就使用第一种,纯标准库实现、功能全面、使用方法偏向传统C++。
  • 如果不介意使用系统API的话就使用第二种,功能简单、使用方法偏向传统C#。

标签:std,C++,elapsed,代码运行,StopWatch,time,Stopwatch,TimeFormat,统计
From: https://www.cnblogs.com/timefiles/p/17374468.html

相关文章

  • C++的友元类
    C++中的友元类是一种特殊的类,它允许一个类授权另一个类或函数访问其私有成员。友元类的使用可以提供更好的封装和安全性,同时也可以增强代码的灵活性和可读性。声明友元类在C++中,声明一个类为另一个类的友元类需要在该类中进行声明。例如,如果类MyClass1希望将类MyClass2声......
  • 【C++之类构造函数和析构函数】
    【C++之类构造函数和析构函数】类的构造函数:1.类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。2.构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回void。3.构造函数可用于为某些成员变量设置初始值。类的析构函数:1.类的析构函......
  • 开心档之C++ 重载运算符和重载函数
    C++重载运算符和重载函数C++允许在同一作用域中的某个函数 和运算符 指定多个定义,分别称为函数重载 和运算符重载。重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它们的参数列表和定义(实现)不相同。当您调用一个重载函数 或重载运算符 时......
  • 编程打卡: C++ 语言程序设计
    #include<iostream>usingnamespacestd;classComplex{protected:doublereal;doubleimag;public:Complex(doubler=0.0,doublei=0.0):real(r),imag(i){};Complexoperator+(constComplex&c){......
  • 【统计数据分析专论】02-Regularization 正则化
    Regularization正则化课件翻译ModelingNonlinearRelation非线性关系建模上节课学了线性模型但是非线性模型也很重要考虑一个由基函数的线性组合定义的模型在数学中,基函数是函数空间中特定基底的元素。函数空间中的每个连续函数可以表示为基函数的线性组合,就像向量......
  • 【C++学习笔记】类的长度
    //空类长度是1由于可以初始化,所以必须有一个长度1class空类{}//一个函数长度是1其实函数不占长度,多个函数,长度还是为1,为了初始化,必须有一个长度。class一个函数{voidTest();}//一个虚函数类由于有一个虚函数表,所以必须长度为4,多个虚函数,也是4class一个虚函数类......
  • C++第四章课后习题4-19
    定义一个CPU类1#include<iostream>2usingnamespacestd;3enumCore{4Single,Dual,Quad5};6enumWords{7Bits32,Bits648};9enumHyperThread{10Support,Notsupport11};12classCPU{13public:14CPU(longint......
  • C++打卡第十八天
    一、问题描述。一个口袋中装有12个球,三个红的,三个白的,六个黑的,现在从中取八个,问有多少种取法。二、设计思路①、我们可以通过定义三个变量,应用循环结构依次遍历可以出现的情况。②、颜色相同的小球大小形状是相同的,那么在相同颜色中选球就是和顺序无关。③、可以通过用所拿出的总......
  • C++获取阿里巴巴1688中国站店铺详情 API 接口返回值示例说明
    ​C++(cplusplus)是一种计算机高级程序设计语言,由C语言扩展升级而产生,最早于1979年由本贾尼·斯特劳斯特卢普在AT&T贝尔工作室研发。C++既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。......
  • C统计单词程序
    C统计单词程序需求描述读取并报告单词的数量计算字符数和行数识别单词的处理把一个单词定义为不含空白的字符序列既:没有空格、制表符、换行符/***@Author:Lucifer*@Date:4/30/2023,2:12:10PM*@LastEditors:Lucifer*@LastEditTime:4/30/2023,2:12:......