统计项目中代码执行耗时
# 程序依赖fmt库
.
├── CMakeLists.txt
├── SpendTimer.cpp
├── SpendTimer.h
├── test.cc
└── third_party
└── fmt
├── include
│ └── fmt
│ ├── chrono.h
│ ├── color.h
│ ├── compile.h
│ ├── core.h
│ ├── format.h
│ ├── format-inl.h
│ ├── locale.h
│ ├── os.h
│ ├── ostream.h
│ ├── posix.h
│ ├── printf.h
│ └── ranges.h
└── lib
├── libfmt.a
├── libfmt.so -> libfmt.so.7
├── libfmt.so.7 -> libfmt.so.7.0.3
└── libfmt.so.7.0.3
# cmake版本设置
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
# 声明项目名称与语言
project(demo LANGUAGES C CXX)
# CMAKE_BUILD_TYPE配置构建类型,默认为空,可以选择Debug 或者 Release
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(POSITION_INDEPENDENT_CODE 1)
set(THIRD_PATH "./third_party")
# 添加第三方库的头文件搜索路径
include_directories(${THIRD_PATH}/fmt/include)
# 添加第三方库的搜索路径
link_directories(${THIRD_PATH}/fmt/lib)
add_executable(test_main test.cc SpendTimer.cpp SpendTimer.h)
target_link_libraries(test_main
PUBLIC
fmt
)
/**
* 程序执行耗时统计计时器,辅助计算代码执行时间
* @note 不建议直接使用,应使用相关工具宏
* @see SPEND_TIME, SPEND_TIME_MSG, SPEND_TIMG_CONTROL
*/
class SpendTimer {
public:
/** 构造函数,记录当前系统时间 */
explicit SpendTimer() : m_msg(""), m_start_time(std::chrono::steady_clock::now()) {}
/**
* 构造函数,记录当前系统时间
* @param msg 辅导输出信息
*/
explicit SpendTimer(const std::string& msg)
: m_msg(msg), m_start_time(std::chrono::steady_clock::now()) {}
/** 析构函数,计算从构造至析构所消耗的时间,并打印输出 */
virtual ~SpendTimer() {
if (m_closed) {
return;
}
std::chrono::duration<double> sec = std::chrono::steady_clock::now() - m_start_time;
double spend = 0;
std::string unit;
if (sec.count() < 0.000001) {
spend = sec.count() * 1000000000;
unit = "ns";
} else if (sec.count() < 0.001) {
spend = sec.count() * 1000000;
unit = "us";
} else if (sec.count() < 1) {
spend = sec.count() * 1000;
unit = "ms";
} else if (sec.count() > 60) {
spend = sec.count() / 60;
unit = " m";
} else if (sec.count() > 86400) {
spend = sec.count() / 360;
unit = " h";
} else {
spend = sec.count();
unit = " s";
}
std::cout << fmt::format("spend time: {:>7.3f} {} | {} ", spend, unit, m_msg) << std::endl;
}
private:
std::string m_msg;
std::chrono::time_point<std::chrono::steady_clock> m_start_time;
static bool m_closed;
friend void close_spend_time();
friend void open_spend_time();
};
/// 全局关闭耗时打印输出
void close_spend_time();
/// 全局开启耗时打印输出
void open_spend_time();
inline void close_spend_time() {
SpendTimer::m_closed = true;
}
inline void open_spend_time() {
SpendTimer::m_closed = false;
}
定义一个耗时计时器开启关闭状态类,如下:
/**
* 耗时计时器开启关闭状态看守,记录之前的耗时开关状态,并置为指定状态,释放时恢复原状态
*/
class SpendTimerGuad {
public:
/**
* 构造函数,记录当前状态,并根据 open 指示开启或关闭耗时统计
* @param open 是否开启耗时统计
*/
explicit SpendTimerGuad(bool open) : m_open(open) {
if (open) {
open_spend_time();
} else {
close_spend_time();
}
}
/** 析构函数,退出当前指定状态,恢复原状态 */
~SpendTimerGuad() {
if (m_open) {
close_spend_time();
} else {
open_spend_time();
}
}
private:
bool m_open;
};
定义一些使用工具宏:
#define SPEND_TIME(id) \
std::stringstream sptmsg_buf_##id(std::stringstream::out); \
sptmsg_buf_##id << #id << " (" << __FILE__ << ":" << __LINE__ << ")"; \
util::SpendTimer test_spend_timer_##id(sptmsg_buf_##id.str());
/**
* 代码执行耗时计时器,附带输出信息
* @param id 自定义耗时计时器id
* @param ... 符合 fmt::format 方式的输出信息
*/
#define SPEND_TIME_MSG(id, ...) \
std::string msg_##id = fmt::format(__VA_ARGS__); \
util::SpendTimer test_spend_timer_##id( \
fmt::format("{} {} ({}:{})", #id, msg_##id, __FILE__, __LINE__));
/**
* 用于动态控制当前代码块及其子块中的耗时计时器,主要用于测试代码中关闭和开启部分耗时统计
*/
#define SPEND_TIMG_CONTROL(open) util::SpendTimerGuad spend_timer_guard_##open(open);
/*
* test.cc
* brief: 测试耗时统计工具
* Created on: 2020-9-5
* Author: erices
*/
#include
#include "SpendTimer.h"
uint64_t Fibonacci(uint32_t i)
{
if (1 == i)
{
return 1;
}
else if(2 == i)
{
return 2;
}
return Fibonacci(i-1) + Fibonacci(i-2);
}
int main()
{
SPEND_TIMG_CONTROL(true);
{
SPEND_TIME_MSG(1, "Fibonacci(20) spend time ");
Fibonacci(20);
}
{
SPEND_TIME_MSG(2, "Fibonacci(30) spend time ");
Fibonacci(30);
}
{
SPEND_TIME_MSG(3, "Fibonacci(40) spend time ");
Fibonacci(40);
}
return 0;
}
# 测试结果
➜ build ./test_main
spend time: 26.933 us | 1 Fibonacci(20) spend time (/root/workspace/util/test.cc:29)
spend time: 3.047 ms | 2 Fibonacci(30) spend time (/root/workspace/util/test.cc:34)
spend time: 346.920 ms | 3 Fibonacci(40) spend time (/root/workspace/util/test.cc:39)
编译注意事项:
由于系统中装了多版本gcc库,故编译时需要显示指定版本。未指定版本
➜ build cmake ..
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /root/workspace/util/build
指定gcc版本:
export CC=/usr/local/bin/gcc
export CXX=/usr/local/bin/g++
➜ build cmake ..
-- The C compiler identification is GNU 9.1.0
-- The CXX compiler identification is GNU 9.1.0
-- Check for working C compiler: /apps/sylar/bin/gcc
-- Check for working C compiler: /apps/sylar/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /apps/sylar/bin/g++
-- Check for working CXX compiler: /apps/sylar/bin/g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /root/workspace/util/build
执行结果:
➜ build ./test_main
spend time: 26.933 us | 1 Fibonacci(20) spend time (/root/workspace/util/test.cc:29)
spend time: 3.047 ms | 2 Fibonacci(30) spend time (/root/workspace/util/test.cc:34)
spend time: 346.920 ms | 3 Fibonacci(40) spend time (/root/workspace/util/test.cc:39)