C++性能测试工具

使用示例main.cpp

// g++-13  -O3  -std=c++17  main.cpp  profile.cpp
#include <iostream>
#include <chrono>
#include <stdint.h>
#include <mutex>       // std::mutex#include "profile.h"
#include "profile_rdtsc.h"std::mutex mutex;uint64_t getTimeHighResolutionClock() {return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock().now().time_since_epoch()).count();
}void batchMeasureClockOverhead(){constexpr int kLoops = 1000;uint64_t t1 = rdtsc();for (int i = 0; i < kLoops; ++i) {getTimeHighResolutionClock();}uint64_t t2 = rdtsc();std::cout << "Batch test, std::chrono::high_resolution_clock() takes " << (t2 - t1) / kLoops << " cycles on average.\n";
}PROFILE_REGISTER(single_measure_clock_overhead);
void singleMeasureClockOverhead(){PROFILE_CHECK(single_measure_clock_overhead);getTimeHighResolutionClock();
}int main() {std::cout << "===Begin of main!===\n";getTimeHighResolutionClock();   // warm upbatchMeasureClockOverhead();constexpr int kLoops = 1000;for (int i = 0; i < kLoops; ++i) {// 这里加锁保护,在多线程中使用此工具需更加注意std::lock_guard guard{mutex};singleMeasureClockOverhead();}std::cout << "===End of main!===\n";
}

profile.h

#ifndef PROFILER_PROFILE_H
#define PROFILER_PROFILE_H#include <iostream>
#include <vector>
#include <set>
#include <string>
#include <string_view>
#include <format>
#include <assert.h>#include "profile_rdtsc.h"#define PF_DEBUG  // open performance test or notnamespace pf {struct ProfileInfo {int id_;int call_count_;uint64_t call_duration_;std::string func_name_;};class Profile {private:Profile() {
#ifdef PF_DEBUGconstexpr int kTimes = 16;for (int i = 0; i < kTimes; ++i) {uint64_t begin = rdtsc_benchmark_begin();uint64_t end = rdtsc_benchmark_end();if (overhead_ > end - begin) {overhead_ = end - begin;   // maybe not the smallest}}
#endif//std::cout << "Profile ctor called.\n";}~Profile() {
#ifdef PF_DEBUGstd::cout << "---> Performance details begin: <---\n";std::cout << "Attention, overhead is " << overhead_<< " cycles, and it is removed from average duration.\n";for (const auto &item: info_) {if (!item.call_count_) {continue;}double average = static_cast<double>(item.call_duration_) / static_cast<double>(item.call_count_) -static_cast<double>(overhead_);if (average < 0) {average = 0.0;  // time cost is smaller than overhead_, because the overhead_ is not accuracy.}std::cout << "[" << item.func_name_ << ", called " << item.call_count_ << " times, total duration cycle is "<< item.call_duration_ << ", average duration cycle is " << average << ".]" << std::endl;}std::cout << "---> Performance details end. <---\n";
#endif}Profile(const Profile &) = delete;Profile &operator=(const Profile &) = delete;public:static Profile &getInstance();void addInfo(int id, uint64_t duration) {assert(id >= 0 && id < static_cast<int>(info_.size()));++info_[id].call_count_;info_[id].call_duration_ += duration;}int registerFunc(const std::string_view func_name) {auto [iter, success] = func_name_.insert(std::string(func_name));assert(success && "One function can only be registered once!");int func_id = static_cast<int>(info_.size());info_.push_back({func_id, 0, 0, *iter});return func_id;}private:std::set<std::string> func_name_;std::vector<ProfileInfo> info_;uint64_t overhead_{~0UL};};class ProfilingChecker {public:ProfilingChecker(int id) : id_(id), start_time_(rdtsc_benchmark_begin()) {//std::cout << "ProfilingChecker ctor called.\n";}~ProfilingChecker() {uint64_t end_time = rdtsc_benchmark_end();uint64_t duration = end_time - start_time_;Profile::getInstance().addInfo(id_, duration);//std::cout << "ProfilingChecker dtor called.\n";}ProfilingChecker(const ProfilingChecker &) = delete;ProfilingChecker &operator=(const ProfilingChecker &) = delete;private:int id_;uint64_t start_time_;};int doProfileRegister(const std::string_view func_name);#ifdef PF_DEBUG
#define PROFILE_REGISTER(func) static const int _pf_id_##func = pf::doProfileRegister(#func);
#define PROFILE_CHECK(func) pf::ProfilingChecker _checker(_pf_id_##func);
#else#define PROFILE_REGISTER(func)
#define PROFILE_CHECK(func)
#endif#ifdef _MSC_VER
#define PROFILE_NOINLINE __declspec(noinline)
#else
#define PROFILE_NOINLINE __attribute__((noinline))
#endif
}#endif //PROFILER_PROFILE_H

profile.cpp

#include "profile.h"
#include <iostream>namespace pf {Profile &Profile::getInstance() {static Profile instance;return instance;}int doProfileRegister(const std::string_view func_name){return Profile::getInstance().registerFunc(func_name);}
}

profile_rdtsc.h


#ifndef PROFILE_PROFILE_RDTSC_H
#define PROFILE_PROFILE_RDTSC_H#include <stdint.h>         // uint64_t#ifndef HAS_HW_RDTSC
#if defined(_M_X64) || defined(_M_IX86) || defined(__x86_64) || defined(__i386)
#define HAS_HW_RDTSC 1
#else
#define HAS_HW_RDTSC 0
#endif
#endif#if HAS_HW_RDTSC
#ifdef _WIN32
#include <intrin.h>        // __rdtsc/_mm_lfence/_mm_mfence
#elif __has_include(<x86intrin.h>)
#include <x86intrin.h>     // __rdtsc/_mm_lfence/_mm_mfence
#endif
#else
#include <chrono>          // std::chrono::steady_clock/nanoseconds
#endif// Macro to forbid the compiler from reordering instructions
#ifdef _MSC_VER
#define RDTSC_MEM_BARRIER() _ReadWriteBarrier()
#else
#define RDTSC_MEM_BARRIER() __asm__ __volatile__("" : : : "memory")
#endifinline uint64_t rdtsc()
{RDTSC_MEM_BARRIER();#if HAS_HW_RDTSCuint64_t result = __rdtsc();
#elseuint64_t result = std::chrono::steady_clock::now().time_since_epoch() /std::chrono::nanoseconds(1);//uint64_t result = std::chrono::high_resolution_clock::now().time_since_epoch() ///                  std::chrono::nanoseconds(1);
#endifRDTSC_MEM_BARRIER();return result;
}#if HAS_HW_RDTSCinline uint64_t rdtsc_benchmark_begin()
{// memory fence, according to x86 architecture,保障开始测试之前让CPU将之前未执行完的指令执行完_mm_mfence();_mm_lfence();uint64_t result = __rdtsc();RDTSC_MEM_BARRIER();return result;
}inline uint64_t rdtsc_benchmark_end()
{_mm_lfence();uint64_t result = __rdtsc();RDTSC_MEM_BARRIER();return result;
}#elseinline uint64_t rdtsc_benchmark_begin()
{return rdtsc();
}inline uint64_t rdtsc_benchmark_end()
{return rdtsc();
}#endif#endif //PROFILE_PROFILE_RDTSC_H

可能的输出结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/802802.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java基于SpringBoot+Vue 的医院预约挂号系统

博主介绍&#xff1a;✌程序员徐师兄、10年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447…

【问题记录】使用Audition播放时低8位数据会被修改

一&#xff0c;问题现象记录 使用Audition连接UAC播放采样点数据比较大的时候&#xff0c;低8位的数据会被修改。如果对低8位数据敏感的情况&#xff0c;需要使用其他播放器进行播放。 二&#xff0c;问题复现 1&#xff0c;使用C代码生成一个PCM文件&#xff1a; #include…

智慧水库解决方案(打造水库智慧监测体系)

​作为一名水利自动化系统集成商,最近我司接手了一个智慧水库建设项目。这个项目位于一座山区的大型水库,目的是对其进行现代化、智能化改造,提升供水、防洪等管理水平。&#xff08;key-iot.com.cn&#xff09; 在方案设计之初,我们组织了现场勘测,全面了解水库的实际情况。这…

win11系统和ubuntu双系统首次连接网线上网流程

硬件准备 首先需要将网线连接到电脑&#xff0c;另一头可以连接交换机或者路由器 上网前需要拨号上网&#xff0c;如果是连的路由器&#xff0c;那么一台路由器上拨号一次就行了。 如果是连的交换机需要拨号上网 这里踩的第一个坑是刚开始电脑连的是交换机1又连的交换机2&…

STM32中C编程引入C++程序

C具备类的创建思想很实用于实际场景多相似性的框架搭建&#xff1b;同种类型或相似类型的C的优势明显因此进行相互嵌套使用 需要在C中使用C类的话&#xff0c;你可以通过C的“extern "C"”语法来实现。这允许你在C代码中使用C的链接方式&#xff0c;而在C代码中使用…

【Linux】UDP编程【上】{诸多编程接口/小白入门式讲解}

文章目录 0.预备知识0.1套接字0.2TCP/UDP0.3大小端问题 1.socket 常见API1.1socket1.2各个接口1.3int bind();1.3网络头文件四件套1.4bzero1.5recvfrom1.6sendto() 2.UDP编程2.1服务器编程2.2客户端编程2.3运行测试2.3.1本机通信2.3.2popen2.3.3strcasestr2.3.4回顾C11智能指针…

微电网优化:基于肝癌算法(Liver Cancer algorithm, LCA)的微电网优化(提供MATLAB代码)

一、微电网优化模型 微电网是一个相对独立的本地化电力单元&#xff0c;用户现场的分布式发电可以支持用电需求。为此&#xff0c;您的微电网将接入、监控、预测和控制您本地的分布式能源系统&#xff0c;同时强化供电系统的弹性&#xff0c;保障您的用电更经济。您可以在连接…

Mamba解读(FlashAttention,SSM,LSSL,S4,S5,Mamba)

Sequence modelScale and EfficiencyFlashAttentionMotivationMethodFlashDecoding MambaState-Space Models&#xff08;SSM&#xff09;Selective State Space Models&#xff08;Mamba&#xff09; Sequence model seq2seq任务将 输入序列 x ( t ) x(t) x(t) 映射为 输出序…

每日两题 / 1.两数之和 49.字母异位词分组(leetcode热题100)

1. 两数之和 - 力扣&#xff08;LeetCode&#xff09; 暴力解法&#xff1a; O ( N 2 ) O(N^2) O(N2)遍历数组&#xff0c;找两个数相加为target O ( N ) O(N) O(N)解法&#xff1a;将所有数排序&#xff0c;并记录这些数的下标&#xff0c;双指针从左右向中间走。指向的两数…

吴恩达深度学习笔记:深层神经网络(Deep Neural Networks)4.1-4.4

目录 第一门课&#xff1a;神经网络和深度学习 (Neural Networks and Deep Learning)第四周&#xff1a;深层神经网络(Deep Neural Networks)4.1 深层神经网络&#xff08;Deep L-layer neural network&#xff09;4.2 前向传播和反向传播&#xff08;Forward and backward pro…

vscode 重命名很慢或失败 vscode renames are slow

网上问题&#xff0c; 插件问题&#xff08;我遇见的排除&#xff0c;不是&#xff09;被其他程序占用问题&#xff0c;&#xff08;我这边是这个&#xff09; 解决方案&#xff1a; 打开【资源管理器】&#xff0c;使用火绒 或其他软件&#xff0c;查看文件夹 or 文件 被哪个…

智慧公厕系统3.0有哪些新功能呢

随着科技的不断进步&#xff0c;智慧公厕系统也在不断升级和完善。最新推出的智慧公厕系统3.0&#xff0c;集成了一系列创新功能&#xff0c;为城市公共卫生设施管理带来了全新的体验和便利。让我们一起来看看智慧公厕系统3.0有哪些新功能吧。 1、云端管理平台&#xff1a;智慧…

家用洗地机哪个牌子好?四大热销机型推荐,值得推荐!

随着科技的进步&#xff0c;洗地机在日常生活中能够帮助人们省时省力地打扫卫生&#xff0c;但市面上出现了各种各样的洗地机&#xff0c;好坏参差不齐&#xff0c;选择一个好品牌的洗地机非常重要&#xff0c;因为它们有着可靠的质量保证。那市面上如此众多的洗地机品牌&#…

8×8点阵数码管显示驱动/大电流数码管驱动IC-VK16K33C SOP20

产品品牌&#xff1a;永嘉微电/VINKA 产品型号&#xff1a;VK16K33C 封装形式&#xff1a;SOP20 概述 VK16K33C是一种带按键扫描接口的数码管或点阵LED驱动控制专用芯片&#xff0c;内部集成有数据锁 存器、键盘扫描、LED 驱动模块等电路。数据通过I2C通讯接口与MCU通信。SE…

为什么电脑越用越慢!

电脑随着时间推移逐渐变慢是一个常见的现象,其背后涉及多种原因。以下是导致电脑运行速度变慢的几个主要因素: 系统资源消耗增加 软件更新与新增应用:随着软件版本的更新和新应用程序的安装,它们往往对硬件资源的需求更高,尤其是对处理器、内存和硬盘的要求。这些新软件可…

Java毕业设计 基于SpringBoot vue流浪动物救助网站

Java毕业设计 基于SpringBoot vue流浪动物救助网站 SpringBoot 流浪动物救助网站 功能介绍 首页 图片轮播 动物领养/捐赠 留言 论坛 发布帖子 公告信息 商品信息 添加购物车 立即购买 寻宠请求 购物车 注册登录 个人中心 余额充值 收货地址 动物收藏 动物领养审核 商品订单 …

6AV6643-5CB10-0BN0触摸屏

6AV6643-5CB10-0BN0触摸屏 6AV6643-5CB10-0BN0触摸屏 6AV6643-5CB10-0BN0触摸屏 商品编号(市售编号) 6AV6643-5CB10-0BN0 产品说明 SIMATIC MP 277 8" 触摸屏 多功能面板带剩磁存储器 7.5" TFT 显示屏 6MByte 项目组态存储器 可项目组态&#xff0c;利用 W…

R语言绘图 | 散点小提琴图

原文链接&#xff1a;R语言绘图 | 散点小提琴图 本期教程 写在前面 本期的图形来自发表在Nature期刊中的文章&#xff0c;这样的基础图形在日常分析中使用频率较高。 获得本期教程数据及代码&#xff0c;后台回复关键词&#xff1a;20240405 绘图 设置路径 setwd("You…

【经典算法】LeetCode 5: 最长回文子串(Java/C/Python3实现含注释说明,Medium)

目录 题目描述思路及实现方式一&#xff1a;动态规划法思路代码实现Java版本C语言版本Python3版本 复杂度分析 方式二&#xff1a;中心扩展法思路代码实现Java版本C语言版本Python3版本 复杂度分析 总结相似题目 标签(题目类型)&#xff1a;回文串、动态规划 题目描述 给定一…

【C++】unordered 系列关联式容器

文章目录 1. unordered 系列关联式容器2. unordered_map2.1 unordered_map 的文档介绍2.2 unordered_map 的接口说明 3. unordered_set4. 在线 OJ 1. unordered 系列关联式容器 在 C 98 中&#xff0c;STL 提供了底层为红黑树结构的一系列关联式容器&#xff0c;在查询时效率可…