gperftools cpp wrapper
gperftools cpp wrapper
// Compile command : ${CXX} -o test_profiler.elf -DUSE_GPERFTOOLS -DDEBUG -D_DEBUG ${CXXFLAGS} -O0 -g -Wall ${LIBS} -lprofiler ${BUILD_LDFLAGS} test_profiler.cpp
// Bash Command : kill -s SIGUSR1 <PID>
// CPU Profiler command : gperftools/bin/pprof -text test_profiler.elf test_profiler.prof
// see https://github.com/gperftools/gperftools/wiki
Source filename: test_profiler.cpp
/* Start of test_profiler.cpp */ // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // Start of config_arch.h #include <climits> /* Whether or not the compiler supports long long and unsigned long long */ #ifndef HAS_LONG_LONG #if __cplusplus >= 201103L #define HAS_LONG_LONG #else #ifdef __GNUG__ #ifdef __SIZEOF_LONG_LONG__ #define HAS_LONG_LONG #endif #endif #endif #endif /* The character type that char matches (i.e., signed or unsigned) */ #if CHAR_MIN < 0 typedef signed char underlying_char_type; #else typedef unsigned char underlying_char_type; #endif // End of config_arch.h // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // Start of config_os.h // ============================================================================= // Determine the platform. Ex., Windows or POSIX. Define feature macros #if ( defined( __unix__ ) || defined( __unix ) || ( defined( __APPLE__ ) && defined( __MACH__ ) ) ) #include <unistd.h> #ifdef _POSIX_VERSION // ISO POSIX.1 aka IEEE 1003.1 /// OS_POSIX - unistd.h is included and _POSIX_VERSION is defined #define OS_POSIX #if _POSIX_VERSION >= 199506L // ISO POSIX.1-1996 aka IEEE 1003.1-1996 #define POSIX_THREADS #if ( _POSIX_VERSION >= 200112L ) // ISO POSIX.1-2001 aka IEEE 1003.1-2001, aka Issue 6, aka SUSv3 #define POSIX_ISSUE_6 #if ( _POSIX_VERSION >= 200809L ) // ISO POSIX.1-2008, aka IEEE 1003.1-2008, aka Issue 7, aka SUSv4 #define POSIX_ISSUE_7 #endif // 2008 #endif // 2001 #endif // 1996 #endif // ifdef _POSIX_VERSION #endif // if ( defined( __unix__ ) || defined( __unix ) || ( defined( __APPLE__ ) && defined( __MACH__ ))) #if defined( _WIN64 ) || defined( _WIN32 ) #include <windows.h> /* MS Windows operating systems */ #define OS_WINDOWS #endif // ============================================================================= // Determine basic types #ifdef OS_POSIX #include <sys/types.h> namespace stdbp { namespace os { // Identifies a user typedef uid_t user_id_type; // Identifies a process typedef pid_t pid_type; } } #else #ifdef OS_WINDOWS namespace stdbp { namespace os { typedef DWORD pid_type; } } #endif // Windows #endif // ifdef OS_POSIX // ============================================================================= // Determine multithreading types #ifdef POSIX_THREADS #include <pthread.h> namespace stdbp { namespace os { typedef pthread_t thread_type; typedef pthread_mutex_t mutex_type; typedef pthread_rwlock_t shared_mutex_type; typedef pthread_cond_t condition_variable_type; } } #else #ifdef OS_WINDOWS namespace stdbp { namespace os { typedef HANDLE thread_type; typedef CRITICAL_SECTION mutex_type; } } #endif #endif // ifdef POSIX_THREADS // End of config_os.h // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // Start of version.h #include <cstddef> #if __cplusplus >= 201703L #define CPP17 #endif #if __cplusplus >= 201402L #define CPP14 #endif #if __cplusplus >= 201103L #define CPP11 #endif #ifdef CPP17 #define CPP17_NAMESPACE std #else #define CPP17_NAMESPACE cpp17 #endif #ifdef CPP14 #define CPP14_NAMESPACE std #else #define CPP14_NAMESPACE cpp14 #endif #ifdef CPP11 #define CPP11_NAMESPACE std #else #define CPP11_NAMESPACE cpp11 #endif namespace cpp11 {} #ifndef CPP11 namespace cpp11 { class nullptr_t { public: nullptr_t() : _pad(0) {} template< class T > operator T *() const { // 定义类型转换操作符,使nullptr_t 可转为任意非类成员指针类型。 return 0; } template< class C, class T > operator T C::*() const { // 重载类型转换操作符,使 nullptr_t 可以转换为类 C 中任意的指针类型(数据成员指针/函数成员指针)。 return 0; } private: void *_pad; // std requires : sizeof(nullptr_t) == sizeof(void*) void operator &() const; // 不允许取地址操作。 }; const nullptr_t nullptr; // 定义 nullptr_t 类型的变量 nullptr } // namespace cpp11 #endif // #ifndef CPP11 namespace cpp14 {} namespace cpp17 {} namespace cpp { using namespace ::std; using namespace ::CPP11_NAMESPACE; using namespace ::CPP14_NAMESPACE; using namespace ::CPP17_NAMESPACE; } // namespace cpp // End of version.h // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // Start of cstdint.h #include <string> //#include "version.h" #ifdef CPP11 // Provided by C++11 #include <cstdint> #else #include <climits> // Steal some types from the implementation, if we can #if !defined( _WIN32 ) && ( defined( __unix__ ) || defined( __unix ) || ( defined( __APPLE__ ) && defined( __MACH__ ))) #include <unistd.h> #if ( _POSIX_C_SOURCE >= 200112L ) // Provided by POSIX #include <stdint.h> namespace cpp11 { using ::intptr_t; using ::uintptr_t; } #endif // POSIX #endif // UNIX-LIKE namespace cpp11 { #define AT_LEAST_16_BITS_S(x) ((x) >= 32767) #define AT_LEAST_32_BITS_S(x) ((x) >= 2147483647) #define AT_LEAST_64_BITS_S(x) ((((((x) >> 15) >> 15) >> 15) >> 15) >= 7) #define AT_LEAST_16_BITS_U(x) ((x) >= 65535) #define AT_LEAST_32_BITS_U(x) (((x) >> 1) >= 2147483647) #define AT_LEAST_64_BITS_U(x) ((((((x) >> 15) >> 15) >> 15) >> 15) >= 15) #define EXACTLY_8_BITS_S(x) ((x) == 127) #define EXACTLY_16_BITS_S(x) ((x) == 32767) #define EXACTLY_32_BITS_S(x) ((x) == 2147483647) #define EXACTLY_64_BITS_S(x) ((((((x) >> 15) >> 15) >> 15) >> 15) == 7) #define EXACTLY_8_BITS_U(x) ((x) == 255) #define EXACTLY_16_BITS_U(x) ((x) == 65535) #define EXACTLY_32_BITS_U(x) (((x) >> 1) == 2147483647) #define EXACTLY_64_BITS_U(x) ((((((x) >> 15) >> 15) >> 15) >> 15) == 15) // int_least8_t typedef signed char int_least8_t; #ifndef INT8_C #define INT8_C(x) x #endif #ifndef INT_LEAST8_MIN #define INT_LEAST8_MIN SCHAR_MIN #endif #ifndef INT_LEAST8_MAX #define INT_LEAST8_MAX SCHAR_MAX #endif // int8_t #if EXACTLY_8_BITS_S(INT_LEAST8_MAX) #ifndef INT8_MIN #define INT8_MIN INT_LEAST8_MIN #endif #ifndef INT8_MAX #define INT8_MAX INT_LEAST8_MAX #endif typedef int_least8_t int8_t; #endif // int_least16_t #if AT_LEAST_16_BITS_S(SCHAR_MAX) typedef signed char int_least16_t; #ifndef INT_LEAST16_MIN #define INT_LEAST16_MIN SCHAR_MIN #endif #ifndef INT_LEAST16_MAX #define INT_LEAST16_MAX SCHAR_MAX #endif #else typedef short int int_least16_t; #ifndef INT_LEAST16_MIN #define INT_LEAST16_MIN SHRT_MIN #endif #ifndef INT_LEAST16_MAX #define INT_LEAST16_MAX SHRT_MAX #endif #endif #ifndef INT16_C #define INT16_C(x) x #endif // int16_t #if EXACTLY_16_BITS_S(INT_LEAST8_MAX) #ifndef INT16_MIN #define INT16_MIN INT_LEAST16_MIN #endif #ifndef INT16_MAX #define INT16_MAX INT_LEAST16_MAX #endif typedef int_least16_t int16_t; #endif // int_least32_t #if AT_LEAST_32_BITS_S(SCHAR_MAX) typedef signed char int_least32_t #ifndef INT_LEAST32_MIN #define INT_LEAST32_MIN SCHAR_MIN #endif #ifndef INT_LEAST32_MAX #define INT_LEAST32_MAX SCHAR_MAX #endif #ifndef INT32_C #define INT32_C(x) x #endif #elif AT_LEAST_32_BITS_S(SHRT_MAX) typedef short int int_least32_t #ifndef INT_LEAST32_MIN #define INT_LEAST32_MIN SHRT_MIN #endif #ifndef INT_LEAST32_MAX #define INT_LEAST32_MAX SHRT_MAX #endif #ifndef INT32_C #define INT32_C(x) x #endif #elif AT_LEAST_32_BITS_S(INT_MAX) typedef int int_least32_t; #ifndef INT_LEAST32_MIN #define INT_LEAST32_MIN INT_MIN #endif #ifndef INT_LEAST32_MAX #define INT_LEAST32_MAX INT_MAX #endif #ifndef INT32_C #define INT32_C(x) x #endif #else typedef long int_least32_t; #ifndef INT_LEAST32_MIN #define INT_LEAST32_MIN LONG_MIN #endif #ifndef INT_LEAST32_MAX #define INT_LEAST32_MAX LONG_MAX #endif #ifndef INT32_C #define INT32_C(x) x##l #endif #endif // if AT_LEAST_32_BITS_S(SCHAR_MAX) // int32_t #if EXACTLY_32_BITS_S(INT_LEAST32_MAX) #ifndef INT32_MIN #define INT32_MIN INT_LEAST32_MIN #endif #ifndef INT32_MAX #define INT32_MAX INT_LEAST32_MAX #endif typedef int_least32_t int32_t; #endif // int_least64_t #if AT_LEAST_64_BITS_S(SCHAR_MAX) typedef signed char int_least64_t #ifndef INT_LEAST64_MIN #define INT_LEAST64_MIN SCHAR_MIN #endif #ifndef INT_LEAST64_MAX #define INT_LEAST64_MAX SCHAR_MAX #endif #ifndef INT64_C #define INT64_C(x) x #endif #elif AT_LEAST_64_BITS_S(SHRT_MAX) typedef short int_least64_t #ifndef INT_LEAST64_MIN #define INT_LEAST64_MIN SHRT_MIN #endif #ifndef INT_LEAST64_MAX #define INT_LEAST64_MAX SHRT_MAX #endif #ifndef INT64_C #define INT64_C(x) x #endif #elif AT_LEAST_64_BITS_S(INT_MAX) typedef int int_least64_t; #ifndef INT_LEAST64_MIN #define INT_LEAST64_MIN INT_MIN #endif #ifndef INT_LEAST64_MAX #define INT_LEAST64_MAX INT_MAX #endif #ifndef INT64_C #define INT64_C(x) x #endif #elif AT_LEAST_64_BITS_S(LONG_MAX) typedef long int_least64_t; #ifndef INT_LEAST64_MIN #define INT_LEAST64_MIN LONG_MIN #endif #ifndef INT_LEAST64_MAX #define INT_LEAST64_MAX LONG_MAX #endif #ifndef INT64_C #define INT64_C(x) x##l #endif #else #ifdef LLONG_MAX typedef long long int_least64_t; #ifndef INT_LEAST64_MIN #define INT_LEAST64_MIN LLONG_MIN #endif #ifndef INT_LEAST64_MAX #define INT_LEAST64_MAX LLONG_MAX #endif #ifndef INT64_C #define INT64_C(x) x##ll #endif #endif #endif // if AT_LEAST_64_BITS_S(SCHAR_MAX) // int64_t #if EXACTLY_64_BITS_S(INT_LEAST64_MAX) #ifndef INT64_MIN #define INT64_MIN INT_LEAST64_MIN #endif #ifndef INT64_MAX #define INT64_MAX INT_LEAST64_MAX #endif typedef int_least64_t int64_t; #endif // uint_least8_t typedef unsigned char uint_least8_t; #ifndef UINT8_C #define UINT8_C(x) x #endif #ifndef UINT_LEAST8_MAX #define UINT_LEAST8_MAX UCHAR_MAX #endif // uint8_t #if EXACTLY_8_BITS_U(UINT_LEAST8_MAX) #ifndef UINT8_MAX #define UINT8_MAX UINT_LEAST8_MAX #endif typedef uint_least8_t uint8_t; #endif // uint_least16_t #if AT_LEAST_16_BITS_U(UCHAR_MAX) typedef unsigned char uint_least16_t; #ifndef UINT_LEAST16_MAX #define UINT_LEAST16_MAX UCHAR_MAX #endif #else typedef unsigned short uint_least16_t; #ifndef UINT_LEAST16_MAX #define UINT_LEAST16_MAX USHRT_MAX #endif #endif #ifndef UINT16_C #define UINT16_C(x) x #endif // uint16_t #if EXACTLY_16_BITS_U(UINT_LEAST16_MAX) #ifndef UINT16_MAX #define UINT16_MAX UINT_LEAST16_MAX #endif typedef uint_least16_t uint16_t; #endif // uint_least32_t #if AT_LEAST_32_BITS_U(UCHAR_MAX) typedef unsigned char uint_least32_t #ifndef UINT_LEAST32_MAX #define UINT_LEAST32_MAX UCHAR_MAX #endif #ifndef UINT32_C #define UINT32_C(x) x #endif #elif AT_LEAST_32_BITS_U(USHRT_MAX) typedef unsigned short uint_least32_t #ifndef UINT_LEAST32_MAX #define UINT_LEAST32_MAX USHRT_MAX #endif #ifndef UINT32_C #define UINT32_C(x) x #endif #elif AT_LEAST_32_BITS_U(UINT_MAX) typedef unsigned uint_least32_t; #ifndef UINT_LEAST32_MAX #define UINT_LEAST32_MAX UINT_MAX #endif #ifndef UINT32_C #define UINT32_C(x) x #endif #else typedef unsigned long uint_least32_t; #ifndef UINT_LEAST32_MAX #define UINT_LEAST32_MAX ULONG_MAX #endif #ifndef UINT32_C #define UINT32_C(x) x##ul #endif #endif // if AT_LEAST_32_BITS_U(UCHAR_MAX) // uint32_t #if EXACTLY_32_BITS_U(UINT_LEAST32_MAX) #ifndef UINT32_MAX #define UINT32_MAX UINT_LEAST32_MAX #endif typedef uint_least32_t uint32_t; #endif // uint_least64_t #if AT_LEAST_64_BITS_U(UCHAR_MAX) typedef unsigned char uint_least64_t #ifndef UINT64_C #define UINT64_C(x) x #endif #ifndef UINT_LEAST64_MAX #define UINT_LEAST64_MAX UCHAR_MAX #endif #elif AT_LEAST_64_BITS_U(USHRT_MAX) typedef unsigned short uint_least64_t #ifndef UINT64_C #define UINT64_C(x) x #endif #ifndef UINT_LEAST64_MAX #define UINT_LEAST64_MAX USHRT_MAX #endif #elif AT_LEAST_64_BITS_U(UINT_MAX) typedef unsigned uint_least64_t; #ifndef UINT64_C #define UINT64_C(x) x #endif #ifndef UINT_LEAST64_MAX #define UINT_LEAST64_MAX UINT_MAX #endif #elif AT_LEAST_64_BITS_U(LONG_MAX) typedef unsigned long uint_least64_t; #ifndef UINT64_C #define UINT64_C(x) x##ul #endif #ifndef UINT_LEAST64_MAX #define UINT_LEAST64_MAX ULONG_MAX #endif #else #ifdef ULLONG_MAX typedef unsigned long long uint_least64_t; #ifndef UINT64_C #define UINT64_C(x) x##ull #endif #ifndef UINT_LEAST64_MAX #define UINT_LEAST64_MAX ULLONG_MAX #endif #endif #endif // if AT_LEAST_64_BITS_U(UCHAR_MAX) // uint64_t #if EXACTLY_64_BITS_U(UINT_LEAST64_MAX) #ifndef UINT64_MAX #define UINT64_MAX UINT_LEAST64_MAX #endif typedef uint_least64_t uint64_t; #endif typedef signed char int_fast8_t; typedef int int_fast16_t; typedef long int_fast32_t; typedef int_least64_t int_fast64_t; typedef unsigned char uint_fast8_t; typedef unsigned uint_fast16_t; typedef unsigned long uint_fast32_t; typedef uint_least64_t uint_fast64_t; #ifdef LLONG_MAX typedef long long intmax_t; #ifndef INTMAX_C #define INTMAX_C(x) x##ll #endif #ifndef INTMAX_MAX #define INTMAX_MAX LLONG_MAX #endif #else typedef long intmax_t; #ifndef INTMAX_C #define INTMAX_C(x) x##l #endif #ifndef INTMAX_MAX #define INTMAX_MAX LONG_MAX #endif #endif #ifdef ULLONG_MAX typedef unsigned long long uintmax_t; #ifndef UINTMAX_C #define UINTMAX_C(x) x##ull #endif #ifndef UINTMAX_MAX #define UINTMAX_MAX ULLONG_MAX #endif #else typedef unsigned long uintmax_t; #ifndef UINTMAX_C #define UINTMAX_C(x) x##ul #endif #ifndef UINTMAX_MAX #define UINTMAX_MAX ULONG_MAX #endif #endif #undef EXACTLY_8_BITS_S #undef EXACTLY_16_BITS_S #undef EXACTLY_32_BITS_S #undef EXACTLY_64_BITS_S #undef EXACTLY_8_BITS_U #undef EXACTLY_16_BITS_U #undef EXACTLY_32_BITS_U #undef EXACTLY_64_BITS_U #undef AT_LEAST_16_BITS_S #undef AT_LEAST_32_BITS_S #undef AT_LEAST_64_BITS_S #undef AT_LEAST_16_BITS_U #undef AT_LEAST_32_BITS_U #undef AT_LEAST_64_BITS_U } // namespace cpp11 #endif // #ifdef CPP11 // End of cstdint.h // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // Start of string.h #include <string> //#include "version.h" #ifndef CPP11 #include <cstdlib> #include <iostream> #include <sstream> //#include "config_arch.h" namespace cpp11 { namespace detail { template< typename I > std::string arithmetic_to_string(I x) { std::ostringstream ss; ss << x; return ss.str(); } template< typename I > std::wstring arithmetic_to_wstring(I x) { std::wostringstream ss; ss << x; return ss.str(); } } // namespace detail inline unsigned long stoul( const std::string &s, std::size_t *pos = 0, int base = 10) { char *ptr; const char *s_ = s.c_str(); const long res = std::strtoul(s_, &ptr, base); if (pos) { *pos = ptr - s_; } return res; } /// @todo Should throw if not convertible, or result is too large inline long stol( const std::string &s, std::size_t *pos = 0, int base = 10) { char * ptr; const char *s_ = s.c_str(); const long res = std::strtol(s_, &ptr, base); if (pos) { *pos = ptr - s_; } return res; } /// @todo Should throw if not convertible, or result is too large inline int stoi( const std::string &s, std::size_t *pos = 0, int base = 10) { return static_cast< int >(stol(s, pos, base)); } /** @brief Get the string representation of an int * @param n An integer * @returns lexical_cast<std::string>(n) */ inline std::string to_string(int n) { return detail::arithmetic_to_string(n); } inline std::string to_string(long n) { return detail::arithmetic_to_string(n); } inline std::string to_string(unsigned n) { return detail::arithmetic_to_string(n); } inline std::string to_string(unsigned long n) { return detail::arithmetic_to_string(n); } #ifdef HAS_LONG_LONG inline std::string to_string(long long n) { return detail::arithmetic_to_string(n); } inline std::string to_string(unsigned long long n) { return detail::arithmetic_to_string(n); } #endif // #ifdef HAS_LONG_LONG inline std::string to_string(float n) { return detail::arithmetic_to_string(n); } inline std::string to_string(double n) { return detail::arithmetic_to_string(n); } inline std::string to_string(long double n) { return detail::arithmetic_to_string(n); } inline std::wstring to_wstring(int n) { return detail::arithmetic_to_wstring(n); } inline std::wstring to_wstring(unsigned n) { return detail::arithmetic_to_wstring(n); } inline std::wstring to_wstring(long n) { return detail::arithmetic_to_wstring(n); } inline std::wstring to_wstring(unsigned long n) { return detail::arithmetic_to_wstring(n); } #ifdef HAS_LONG_LONG inline std::wstring to_wstring(long long n) { return detail::arithmetic_to_wstring(n); } inline std::wstring to_wstring(unsigned long long n) { return detail::arithmetic_to_wstring(n); } #endif // #ifdef HAS_LONG_LONG inline std::wstring to_wstring(float n) { return detail::arithmetic_to_wstring(n); } inline std::wstring to_wstring(double n) { return detail::arithmetic_to_wstring(n); } inline std::wstring to_wstring(long double n) { return detail::arithmetic_to_wstring(n); } } // namespace cpp11 #endif // #ifndef CPP11 // End of string.h // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< //#include "version.h" //#include "config_arch.h" //#include "config_os.h" //#include "cstdint.h" //#include "string.h.h" #include <cstdio> #include <cstdlib> #include <cerrno> #include <csignal> #include <ctime> #include <cstring> #include <sstream> namespace lse_ns_util { namespace common { char *GetFilename(const char *fullname) { char *name = cpp::nullptr; #if ( defined( __unix__ ) || defined( __unix ) || ( defined( __APPLE__ ) && defined( __MACH__ ) ) ) const char splitchar = '/'; #elif defined( _WIN64 ) || defined( _WIN32 ) const char splitchar = '\\'; #else const char splitchar = '\ '; #endif if (fullname == cpp::nullptr || *fullname == '\0') { return cpp::nullptr; } for (char *ptr = (char *)fullname; *ptr != '\0'; ptr++) { if (*ptr == splitchar && *(ptr + 1) != '\0') { name = ptr; } } // eg: fullname == "/" if (name == cpp::nullptr && *fullname == splitchar) { return cpp::nullptr; } // eg: fullname == "xxx.elf/" if (name == cpp::nullptr && (*(fullname + strlen(fullname) - 1) == splitchar) ) { return cpp::nullptr; } // eg: fullname == "/yyy/xxx.elf/" if (name != cpp::nullptr && (*(fullname + strlen(fullname) - 1) == splitchar)) { return cpp::nullptr; } // eg: fullname == "xxx.elf" if (name == cpp::nullptr && *fullname != splitchar) { return (char *)fullname; } // eg: fullname == "/xxx.elf" if ((name != cpp::nullptr && name == fullname)) { return (name + 1); } // eg: fullname == "/yyy/xxx.elf" if (name != cpp::nullptr && name != fullname) { return (name + 1); } return cpp::nullptr; } size_t GetPathname(const char *fullname, char *pathname, const size_t pathszie) { char *name = cpp::nullptr; #if ( defined( __unix__ ) || defined( __unix ) || ( defined( __APPLE__ ) && defined( __MACH__ ) ) ) const char splitchar = '/'; const char *splitstr = "/"; #elif defined( _WIN64 ) || defined( _WIN32 ) const char splitchar = '\\'; const char *splitstr = "\\"; #else const char splitchar = '\ '; const char *splitstr = "\ "; #endif if (fullname == cpp::nullptr || *fullname == '\0' || pathname == cpp::nullptr || pathszie < 2) { return 0; } for (char *ptr = (char *)fullname; *ptr != '\0'; ptr++) { if (*ptr == splitchar && *(ptr + 1) != '\0') { name = ptr; } } // eg: fullname == "/" if (name == cpp::nullptr && *fullname == splitchar) { strncpy(pathname, splitstr, strlen(splitstr)); return strlen(pathname); } // eg: fullname == "xxx.elf/" if (name == cpp::nullptr && (*(fullname + strlen(fullname) - 1) == splitchar)) { strncpy(pathname, ".", strlen(".")); return strlen(pathname); } // eg: fullname == "/yyy/xxx.elf/" if (name != cpp::nullptr && (*(fullname + strlen(fullname) - 1) == splitchar)) { if (pathszie > (size_t)(name - fullname)) { strncpy(pathname, fullname, (size_t)(name - fullname)); return strlen(pathname); } else { return 0; } } // eg: fullname == "xxx.elf" if (name == cpp::nullptr && *fullname != splitchar) { strncpy(pathname, ".", strlen(".")); return strlen(pathname); } // eg: fullname == "/xxx.elf" if ((name != cpp::nullptr && name == fullname)) { strncpy(pathname, splitstr, strlen(splitstr)); return strlen(pathname); } // eg: fullname == "/yyy/xxx.elf" if (name != cpp::nullptr && name != fullname) { if (pathszie > (size_t)(name - fullname)) { strncpy(pathname, fullname, (size_t)(name - fullname)); return strlen(pathname); } else { return 0; } } return 0; } size_t DelLastSuffix(const char *filename, const char splitchar, char *newname, const size_t newszie) { char *name = cpp::nullptr; const char splitstr[] = { splitchar, '\0' }; if (filename == cpp::nullptr || *filename == '\0' || newname == cpp::nullptr || newszie < 2) { return 0; } for (char *ptr = (char *)filename; *ptr != '\0'; ptr++) { if (*ptr == splitchar && *(ptr + 1) != '\0') { name = ptr; } } // eg: filename == "." if (name == cpp::nullptr && *filename == splitchar) { strncpy(newname, splitstr, strlen(splitstr)); return strlen(newname); } // eg; filename == "xxx." if (name == cpp::nullptr && (*(filename + strlen(filename) - 1) == splitchar)) { if (newszie > strlen(filename) - 1) { strncpy(newname, filename, strlen(filename) - 1); return strlen(newname); } else { return 0; } } // eg; filename == "yyy.xxx." if (name != cpp::nullptr && (*(filename + strlen(filename) - 1) == splitchar)) { if (newszie > (size_t)(name - filename)) { strncpy(newname, filename, (size_t)(name - filename)); return strlen(newname); } else { return 0; } } // eg: filename == "xxx" if (name == cpp::nullptr && *filename != splitchar) { if (newszie > strlen(filename)) { strncpy(newname, filename, strlen(filename)); return strlen(newname); } else { return 0; } } // eg: filename == ".xxx" if ((name != cpp::nullptr && name == filename)) { strncpy(newname, splitstr, strlen(splitstr)); return strlen(newname); } // eg: filename == "xxx.yyy.zzz" if (name != cpp::nullptr && name != filename) { if (newszie > (size_t)(name - filename)) { strncpy(newname, filename, (size_t)(name - filename)); return strlen(newname); } else { return 0; } } return 0; } int setupSignal(int signum, void(*handler) (int)) { const size_t MAX_BUF_LEN = 1024; char strbuf[MAX_BUF_LEN] = {'\0'}; struct sigaction s_sigAction; s_sigAction.sa_handler = handler; s_sigAction.sa_flags = 0; sigemptyset(&s_sigAction.sa_mask); sigaddset(&s_sigAction.sa_mask, signum); if (sigaction(signum, &s_sigAction, cpp::nullptr) < 0) { strerror_r(errno, strbuf, MAX_BUF_LEN); fprintf(stderr, "error: %d - %s", errno, strbuf); return errno; } else { return 0; } } std::string TimeToTimestampStr(time_t t) { tm dTm; tm* aTm = localtime_r(&t, &dTm); const size_t MAX_BUF_LEN = 20; char strbuf[MAX_BUF_LEN] = { '\0' }; // YYYY year // MM month (2 digits 01-12) // DD day (2 digits 01-31) // HH hour (2 digits 00-23) // MM minutes (2 digits 00-59) // SS seconds (2 digits 00-59) snprintf(strbuf, MAX_BUF_LEN, "%04d-%02d-%02d_%02d:%02d:%02d", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec); return std::string(strbuf); } uint32_t CreatePIDFile(std::string filename) { FILE * pid_file = fopen(filename.c_str(), "w"); if (pid_file == cpp::nullptr) { return 0; } #ifdef WIN32 DWORD pid = GetCurrentProcessId(); #else pid_t pid = getpid(); #endif fprintf(pid_file, "%d", pid); fclose(pid_file); return (uint32_t)pid; } } namespace prof { #if (defined(__linux__) || defined(__FreeBSD__)) && defined(USE_GPERFTOOLS) #include <gperftools/profiler.h> #endif class Profiler { public: static Profiler *getInstance() { return instance; } static Profiler *FreeInstance() { if (instance != cpp::nullptr) { delete instance; instance = cpp::nullptr; } return instance; } bool IsRunning() const { #if (defined(__linux__) || defined(__FreeBSD__)) && defined(USE_GPERFTOOLS) ProfilerState state; ProfilerGetCurrentState(&state); return state.enabled; #else return false; #endif } void Flush() { #if (defined(__linux__) || defined(__FreeBSD__)) && defined(USE_GPERFTOOLS) ProfilerFlush(); #endif } void RegisterThread() { #if (defined(__linux__) || defined(__FreeBSD__)) && defined(USE_GPERFTOOLS) ProfilerRegisterThread(); #endif } bool Start(std::string filename, std::string &failureReason) { #if (defined(__linux__) || defined(__FreeBSD__)) && defined(USE_GPERFTOOLS) if (IsRunning()) { failureReason = "Already running"; return false; } if (ProfilerStart(filename.c_str()) == 0) { failureReason = "ProfilerStart returned an error"; return false; } return true; #else failureReason = "Not compiled with gperftools"; return false; #endif } bool Stop(std::string &failureReason) { #if (defined(__linux__) || defined(__FreeBSD__)) && defined(USE_GPERFTOOLS) if (!IsRunning()) { failureReason = "Not running"; return false; } ProfilerStop(); return true; #else failureReason = "Not compiled with gperftools"; return false; #endif } std::string GetInfos() const { #if (defined(__linux__) || defined(__FreeBSD__)) && defined(USE_GPERFTOOLS) bool enabledForAllThreads = ProfilingIsEnabledForAllThreads(); ProfilerState state; ProfilerGetCurrentState(&state); std::stringstream infos; infos.str(""); infos.clear(); infos << "Profiling is " << std::endl; infos << "- " << (state.enabled ? "enabled" : "disabled") << std::endl; if (!IsRunning()) { return infos.str(); } infos << "- " << (enabledForAllThreads ? "" : "not ") << "enabled for all threads" << std::endl; infos << "- Started at timestamp(" << cpp::to_string(state.start_time) << ") / localtime(" << ::lse_ns_util::common::TimeToTimestampStr(state.start_time) << ")" << std::endl; infos << "- Writing to filename(" << state.profile_name << ")" << std::endl; infos << "- Has currently gathered " << cpp::to_string(state.samples_gathered) << " samples" << std::endl; return infos.str(); #else return "Not compiled with gperftools"; #endif } private: static Profiler *instance; // 声明的静态成员变量 instance Profiler() {} }; // 定义 Profiler 类的静态成员变量 instance Profiler *Profiler::instance = new Profiler(); } // namespace prof namespace util { using namespace ::lse_ns_util::common; using namespace ::lse_ns_util::prof; } } // namespace lse_ns_util #include <csignal> #include <iostream> void profilerSignalHandler(int signum) { static bool isRunning = false; if (signum != SIGUSR1) { return; } const char *profilerDefaultname = "test"; const char *profilerSuffix = ".prof"; const size_t MAX_FILENAME_LEN = 256; char profilerFilename[MAX_FILENAME_LEN] = { '\0' }; std::string strTemp; std::string strFilename; strFilename.erase(); strFilename.clear(); if (lse_ns_util::util::DelLastSuffix(lse_ns_util::util::GetFilename(__FILE__), '.', profilerFilename, MAX_FILENAME_LEN) != 0) { strFilename.append(profilerFilename).append(profilerSuffix); } else { strFilename.append(profilerDefaultname).append(profilerSuffix); } strTemp.erase(); strTemp.clear(); lse_ns_util::util::Profiler * profiler = lse_ns_util::util::Profiler::getInstance(); isRunning = profiler->IsRunning(); if (!isRunning) { profiler->Start(strFilename, strTemp); isRunning = profiler->IsRunning(); if (isRunning) { std::cout << profiler->GetInfos() << std::endl; std::cout << "Notice: Profiler Start successfully." << std::endl; } else { std::cout << "Notice: Profiler Start failed." << std::endl; } } else { profiler->Stop(strTemp); isRunning = profiler->IsRunning(); if (!isRunning) { lse_ns_util::util::Profiler::FreeInstance(); std::cout << "Notice: Profiler Stop successfully." << std::endl; } else { std::cout << "Notice: Profiler Stop failed." << std::endl; } } } void loopop() { int n = 0; while (1) { for (int i = 0; i < 10000; i++) { for (int j = 0; j < 10000; j++) { n |= i % 100 + j / 100; } } std::cout << lse_ns_util::common::TimeToTimestampStr(time(cpp::nullptr)) << " - result: " << n << std::endl; } return; } // Compile command : ${CXX} -o test_profiler.elf -DUSE_GPERFTOOLS -DDEBUG -D_DEBUG ${CXXFLAGS} -O0 -g -Wall ${LIBS} -lprofiler ${BUILD_LDFLAGS} test_profiler.cpp // Bash Command : kill -s SIGUSR1 <PID> // CPU Profiler command : gperftools/bin/pprof -text test_profiler.elf test_profiler.prof // see https://github.com/gperftools/gperftools/wiki int main(int argc, char *argv[]) { if (lse_ns_util::util::setupSignal(SIGUSR1, profilerSignalHandler) != 0) { return -1; } else { loopop(); return 0; } } /* End of test_profiler.cpp */
==================== End