开发者

C++统计函数执行时间的最佳实践

开发者 https://www.devze.com 2025-09-03 10:34 出处:网络 作者: 天天进步2015
目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法输出示例实现亮点1. 线程安全保证2. 异常安全3. 内存管理性能考量扩展建议适用场景总结完整代码function_timer.h
目录
  • 前言
  • 工具特性
  • 核心设计
    • 1. 数据结构设计
    • 2. 单例模式管理器
    • 3. RAII自动计时
  • 使用方法
    • 基本用法
    • 高级用法
  • 输出示例
    • 实现亮点
      • 1. 线程安全保证
      • 2. 异常安全
      • 3. 内存管理
    • 性能考量
      • 扩展建议
        • 适用场景
          • 总结
            • 完整代码
              • function_timer.h
              • function_timer.cpp

            前言

            在软件开发过程中,性能分析是优化程序的重要环节。特别是在C++这样的高性能语言中,了解函数的执行时间分布对于识别性能瓶颈至关重要。今天我们来介绍一个轻量级的C++函数执行时间统计工具,它能够帮助开发者快速定位性能问题。

            工具特性

            这个函数计时器具有以下核心特性:

            功能完备性

            • 统计函数调用次数、总执行时间、平均时间、最小时间、最大时间
            • 支持多函数同时监控
            • 提供统计报告输出和数据清理功能

            易用性

            • 使用RAII(Resource Acquisition Is Initialization)机制自动计时
            • 一行宏定义即可启用监控:TIMER_SCOPE("函数名")
            • 无侵入性设计,不影响原有代码逻辑

            线程安全性

            • 使用互斥锁保护共享数据
            • 支持多线程环境下的并发使用

            性能友好

            • 基于std::chrono::steady_clock提供高精度计时
            • 单例模式减少内存开销

            核心设计

            1. 数据结构设计

            struct FunctionStats {
                std::string functionName;
                long totalTimeMs;      // 总执行时间
                int callCount;         // 调用次数
                long minTimeMs;        // 最小执行时间
                long maxTimeMs;        // 最大执行时间
                double avgTimeMs;      // 平均执行时间
            };
            

            FunctionStats 结构体封装了单个函数的完整统计信息,通过 addExecution 方法动态更新统计数据。

            2. 单例模式管理器

            FunctionTimer 类采用线程安全的单例模式,确保全局只有一个统计管理器实例:

            static FunctionTimer* getInstance() {
                std::lock_guard<std::mutex> lock(instanceMutex);
                if (instance == nullptr) {
                    instance = std::unique_ptr<FunctionTimer>(new FunctionTimer());
                }
                return instance.get();
            }
            

            3. RAII自动计时

            ScopedTimer 类是整个工具的核心,利用C++的RAII特性实现自动计时:

            class ScopedTimer {
                std::string functionName;
                std::chrono::steady_clock::time_point startTime;
            public:
                explicit ScopedTimer(const std::string& funcName);
                ~ScopedTimer();  // 析构时自动记录执行时间
            };
            

            当对象创建时记录开始时间,当对象销毁(离开作用域)时自动计算并记录执行时间。

            使用方法

            基本用法

            #include "function_timer.h"
            
            void someFunction() {
                TIMER_SCOPE("someFunction");  // 添加这一行即可
                
                // 原有的函数逻辑
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
            }
            
            int main() {
                // 执行一些被监控的函数
                for(int i = 0; i < 10; i++) {
                    someFunction();
                }
                
                // 打印统计报告
                FunctionTimer::getInstance()->printStats();
                
                return 0;
            }
            

            高级用法

            // 获取特定函数的统计信息
            FunctionStats stats = FunctionTimer::getInstance()->getFunctionStats("someFunction");
            std::cout << "函数调用了 php" << stats.callCount << " 次" << std::endl;
            
            // 获取所有统计数据
            auto allStats = FunctionTimer::getInstance()->getAllStats();
            for(const auto& pair : allStats) {
                std::cout << pair.first << ": " << pair.second.avgTimeMs << "ms" << std::endl;
            }
            
            // 清理统计数据
            FunctionTimer::getInstance()->clearStats();
            

            输出示例

            ========== 函数执行时间统计报告 ==========

            函数名称 | 调用次数 | 总时间(ms) | 平均时间(ms) | 最小时间(ms) | 最大时间(ms)

            ----------------------------------------------------------------------

            someFunction | 10 | 1005 | 100 | 99 | 102

            anotherFunction | 5 | 250 | 50 | 48 | 53

            ==========================================

            实现亮点

            1. 线程安全保证

            使用std::mutexstd::lock_guard确保多线程环境下的数据一致性:

            void recordExecution(const std::string& functionName, long executionTimeMs) {
                std::lock_guard<std::mutex> lock(statsMutex);
                // 线程安全的数据更新
                stats[functionName].addExecution(executionTimeMs);
            }
            

            2. 异常安全

            即使函数执行过程中抛出异常,ScopedTimer 的析构函数仍会被调用,确保计时统计的准确性。

            3. 内存管理

            使用智能指针std::unique_ptr管理单例实例,避免内存泄漏。

            性能考量

            这个工具设计时充分考虑了性能影响:

            • 时间复杂度:记录操作为O(1),查询操作为O(1)
            • 空间复杂度:每个监控函数只需少量内存存储统计信息
            • 运行时开销:主要开销来自时间获取和互斥锁操作,影响极小

            扩展建议

            添加采样功能:对于高频调用的函数,可以添加采样机制减少性能影响

            支持更多统计指标:如95百分位数、标准差等

            可视化输出:生成图表或jsON格式的统计报告

            持久化存储:将统计数据保存到文件中供后续分析

            适用场景

            这个工具特别适用于以下场景:

            • 性能调优阶段:识别热点函数和性能瓶颈
            • 算法比较:对比不同算法实现的性能差异
            • 回归测试:监控性能回归问题
            • 生产环境监控:轻量级的性能监控(建议添加开关控制)

            总结

            这个C++函数执行时间统计工具虽然简洁,但功能完备、使用方便。它体现了优秀工具设计的几个原则:

            • 简单易用:一行代码即可启用监控
            • 功能完整:提供全面的统计信息
            • 性能友好:最小化对原程序的影响
            • 线程安全:支持多线程环境

            对于需要进行性能分析的C++项目,这是一个非常实用的工具。通过合理使用,开发者可以快速定位性能问题,提升程序效率。

            完整代码

            function_timer.h

            #pragma once
            
            #include <chrono>
            #include <string>
            #include <unordered_map>
            #include <memory>
            #include <mutex>
            #include <climits>
            
            struct FunctionStats {
                std::string functionName;
                long totalTimeMs;
                int callCount;
                long minTimeMs;
                long maxTimeMs;
                double avgTimeMs;
                    
                FunctionStats() : totalTimeMs(0), callCount(0), minTimeMs(LONG_MAX), maxTimeMs(0), avgTimeMs(0.0) {}
                    
                void addExecution(long executionTimeMs) {
                    totalTimeMs += executionTimeMs;
                    callCount++;
                    if (executionTimeMs < minTimeMs) minTimeMs = executionTimeMs;
                    if (executionTimeMs > maxTimeMs) maxTimeMs = executionTimeMs;
                    avgTimeMs = static_cast<double>(totalTimeMs) / callCount;
                }
            };
            
            class FunctionTimer {
            private:
                static std::unique_ptr<FunctionTimer> instance;
                static std::mutex instanceMutex;
                    
                std::unordered_map<std::string, FunctionStats> stats;
                mutable std::mutex statsMutex;
                    
                FunctionTimer() = default;
            
            public:
                static FunctionTimer* getInstance();
                    
                void recordExecution(const std::string& functionName, long executionTimeMs);
                void printStats() const;
                void clearStats();
                FunctionStats getFunctionStats(const std::string& functionName) const;
                std::unordere编程客栈d_map<std::string, FunctionStats> getAllStats() const;
            };
            
            class ScopedTimer {
            private:
                std::string functionName;
                std::chrono::steady_clock::time_point startTime;
                
            public:
                explicit ScopedTimer(const std::string& funcName);
                ~ScopedTimer();
            };
            
            #define TIMER_SCOPE(funcName) ScopedTimer timer(funcName)
            

            function_timer.cpp

            #include "../include/function_timer.h"
            #include <IOStream>
            #include <iomanip>
            #include <climits>
            #include "../../common/logging/log_helper.h"
            
            std::unique_ptr<FunctionTimer> FunctionTimer::instance = nullptr;
            std::mutex FunctionTimer::instanceMutex;
            
            FunctionTimer* FunctionTimer::getInstance() {
                std::lock_guard<std::mutex> lock(instanceMutex);
                if (instance == nullptr) {
                    instance = std::unique_ptr<FunctionTimer>(new FunctionTimer());
                }
                return instance.get();
            }
            
            void FunctionTimer::recordExecution(const std::string& functionName, long executionTimeMs) {
                std::lock_guard<std:www.devze.com:mutex> lock(statsMutex);
                    
                if (stats.find(functionName) == stats.end()) {
                    stats[functionName].functionName = functionName;
                }
                    
                stats[functionName].addExecution(executionTimeMs);
            }
            
            void FunctionTimer::printStats() const {
                std::lock_guard<std::mutex> lock(statsMutex);
                    
                LogHelper::logInfo("========== 函数执行时间统计报告 ==========");
                LogHelper::logInfo("函数名称 | 调用次数 | 总时间(ms) | 平均时间(ms) | 最小时间(ms) | 最大时间(ms)");
                LogHelper::logInfo("----------------------------------------------------------------------");
                    
                for (const auto& pair : stats) {
                    const FunctionStats& stat = pair.second;
                    std::string logMsg = stat.functionName + " | " +
                                        std::to_string(stat.callCount) + " | " +
                                        std::to_string(stat.totalTimeMs) + " | " +
                                        std::to_string(static_cast<long>(stat.avgTimeMs)) + " | " +
                                        std::to_string(stat.minTimeMs == LONG_MAX ? 0 : stat.minTimeMs) + " | " +
                                    js    std::to_string(stat.maxTimeMs);
                    LogHelper::logInfo(logMsg);
                }
                    
                LogHelper::logInfo("==========================================");
            }
            
            void FunctionTimer::clearStats() {
                std::lock_guard<std::mutex> lock(statsMutex);
                stats.clear();
            }
            
            FunctionStats FunctionTimer::getFunctionStats(const std::string& functionName) const {
                std::lock_guard<std::mutex> lock(statsMutex);
                auto it = stats.find(functionName);
                if (it != stats.end()) {
                    return it->second;
                }
                return FunctionStats();
            }
            
            std::unordered_map<std::string, FunctionStats> FunctionTimer::getAllStats() const {
                std::lock_guard<std::mutex> lock(statsMutex);
                return stats;
            }
            
            ScopedTimer::ScopedTimer(const std::string& funcName) 
                : functionName(funcName), startTime(std::phpchrono::steady_clock::now()) {
            }
            
            ScopedTimer::~ScopedTimer() {
                auto endTime = std::chrono::steady_clock::now();
                auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime);
                long executionTimeMs = duration.count();
                    
                FunctionTimer::getInstance()->recordExecution(functionName, executionTimeMs);
            }
            

            以上就是C++统计函数执行时间的最佳实践的详细内容,更多关于C++统计函数执行时间的资料请关注编程客栈(www.devze.com)其它相关文章!

            0

            上一篇:

            没有了:下一篇

            精彩评论

            暂无评论...
            验证码 换一张
            取 消

            关注公众号