Loading 3party/gperftools/src/profiler.cc +298 −254 Original line number Diff line number Diff line Loading @@ -36,10 +36,10 @@ #include "config.h" #include "getpc.h"// should be first to get the _GNU_SOURCE dfn #include <signal.h> #include <assert.h> #include <stdio.h> #include <errno.h> #include <signal.h> #include <stdio.h> #include <string.h> #ifdef HAVE_UNISTD_H #include <unistd.h>// for getpid() Loading @@ -54,17 +54,17 @@ typedef ucontext ucontext_t; #else typedef int ucontext_t;// just to quiet the compiler, mostly #endif #include <sys/time.h> #include <string> #include <gperftools/profiler.h> #include <gperftools/stacktrace.h> #include "base/commandlineflags.h" #include "base/logging.h" #include "base/googleinit.h" #include "base/logging.h" #include "base/spinlock.h" #include "base/sysinfo.h" /* for GetUniquePathFromEnv, etc */ #include "profiledata.h" #include "profile-handler.h" #include "profiledata.h" #include <gperftools/profiler.h> #include <gperftools/stacktrace.h> #include <string> #include <sys/time.h> using std::string; Loading Loading @@ -133,13 +133,13 @@ class CpuProfiler { void DisableHandler(); // Signal handler that records the interrupted pc in the profile data. static void prof_handler(int sig, siginfo_t*, void* signal_ucontext, void* cpu_profiler); static void prof_handler(int sig, siginfo_t *, void *signal_ucontext, void *cpu_profiler); }; // Signal handler that is registered when a user selectable signal // number is defined in the environment variable CPUPROFILESIGNAL. static void CpuProfilerSwitch(int signal_number) static void CpuProfilerSwitch(int signal_number) { static unsigned profile_count; static char base_profile_name[PATH_MAX]; Loading @@ -152,18 +152,17 @@ static void CpuProfilerSwitch(int signal_number) } } if (!started) { char full_profile_name[PATH_MAX + 16]; snprintf(full_profile_name, sizeof(full_profile_name), "%s.%u", base_profile_name, profile_count++); snprintf(full_profile_name, sizeof(full_profile_name), "%s.%u", base_profile_name, profile_count); if (!started) { ++profile_count; if (!ProfilerStart(full_profile_name)) { RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n", full_profile_name, strerror(errno)); RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n", full_profile_name, strerror(errno)); } RAW_LOG(INFO, "Start New cpu Profiling for '%s'", full_profile_name); } else { ProfilerStop(); RAW_LOG(INFO, "Stop cpu Profiling for '%s'", full_profile_name); } started = !started; } Loading @@ -174,8 +173,8 @@ static void CpuProfilerSwitch(int signal_number) CpuProfiler CpuProfiler::instance_; // Initialize profiling: activated if getenv("CPUPROFILE") exists. CpuProfiler::CpuProfiler() : prof_handler_token_(NULL) { CpuProfiler::CpuProfiler() : prof_handler_token_(NULL) { // TODO(cgd) Move this code *out* of the CpuProfile constructor into a // separate object responsible for initialization. With ProfileHandler there // is no need to limit the number of profilers. Loading Loading @@ -219,27 +218,24 @@ CpuProfiler::CpuProfiler() } if (!Start(fname, NULL)) { RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n", fname, strerror(errno)); RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n", fname, strerror(errno)); } } } bool CpuProfiler::Start(const char* fname, const ProfilerOptions* options) { bool CpuProfiler::Start(const char *fname, const ProfilerOptions *options) { SpinLockHolder cl(&lock_); if (collector_.enabled()) { return false; } if (collector_.enabled()) { return false; } ProfileHandlerState prof_handler_state; ProfileHandlerGetState(&prof_handler_state); ProfileData::Options collector_options; collector_options.set_frequency(prof_handler_state.frequency); if (!collector_.Start(fname, collector_options)) { return false; } if (!collector_.Start(fname, collector_options)) { return false; } filter_ = NULL; if (options != NULL && options->filter_in_thread != NULL) { Loading @@ -253,17 +249,15 @@ bool CpuProfiler::Start(const char* fname, const ProfilerOptions* options) { return true; } CpuProfiler::~CpuProfiler() { Stop(); } CpuProfiler::~CpuProfiler() { Stop(); } // Stop profiling and write out any collected profile data void CpuProfiler::Stop() { void CpuProfiler::Stop() { SpinLockHolder cl(&lock_); if (!collector_.enabled()) { return; } if (!collector_.enabled()) { return; } // Unregister prof_handler to stop receiving SIGPROF interrupts before // stopping the collector. Loading @@ -274,12 +268,12 @@ void CpuProfiler::Stop() { collector_.Stop(); } void CpuProfiler::FlushTable() { void CpuProfiler::FlushTable() { SpinLockHolder cl(&lock_); if (!collector_.enabled()) { return; } if (!collector_.enabled()) { return; } // Unregister prof_handler to stop receiving SIGPROF interrupts before // flushing the profile data. Loading @@ -292,12 +286,16 @@ void CpuProfiler::FlushTable() { EnableHandler(); } bool CpuProfiler::Enabled() { bool CpuProfiler::Enabled() { SpinLockHolder cl(&lock_); return collector_.enabled(); } void CpuProfiler::GetCurrentState(ProfilerState* state) { void CpuProfiler::GetCurrentState(ProfilerState *state) { ProfileData::State collector_state; { SpinLockHolder cl(&lock_); Loading @@ -312,13 +310,17 @@ void CpuProfiler::GetCurrentState(ProfilerState* state) { state->profile_name[buf_size - 1] = '\0'; } void CpuProfiler::EnableHandler() { void CpuProfiler::EnableHandler() { RAW_CHECK(prof_handler_token_ == NULL, "SIGPROF handler already registered"); prof_handler_token_ = ProfileHandlerRegisterCallback(prof_handler, this); RAW_CHECK(prof_handler_token_ != NULL, "Failed to set up SIGPROF handler"); } void CpuProfiler::DisableHandler() { void CpuProfiler::DisableHandler() { RAW_CHECK(prof_handler_token_ != NULL, "SIGPROF handler is not registered"); ProfileHandlerUnregisterCallback(prof_handler_token_); prof_handler_token_ = NULL; Loading @@ -330,12 +332,12 @@ void CpuProfiler::DisableHandler() { // access the data touched by prof_handler() disable this signal handler before // accessing the data and therefore cannot execute concurrently with // prof_handler(). void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext, void* cpu_profiler) { void CpuProfiler::prof_handler(int sig, siginfo_t *, void *signal_ucontext, void *cpu_profiler) { CpuProfiler *instance = static_cast<CpuProfiler *>(cpu_profiler); if (instance->filter_ == NULL || (*instance->filter_)(instance->filter_arg_)) { if (instance->filter_ == NULL || (*instance->filter_)(instance->filter_arg_)) { void *stack[ProfileData::kMaxStackDepth]; // Under frame-pointer-based unwinding at least on x86, the Loading @@ -350,8 +352,7 @@ void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext, // "pprof" at analysis time. Instead of skipping the top frames, // we could skip nothing, but that would increase the profile size // unnecessarily. int depth = GetStackTraceWithContext(stack + 1, arraysize(stack) - 1, 3, signal_ucontext); int depth = GetStackTraceWithContext(stack + 1, arraysize(stack) - 1, 3, signal_ucontext); void **used_stack; if (depth > 0 && stack[1] == stack[0]) { Loading @@ -369,38 +370,51 @@ void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext, #if !(defined(__CYGWIN__) || defined(__CYGWIN32__)) extern "C" PERFTOOLS_DLL_DECL void ProfilerRegisterThread() { extern "C" PERFTOOLS_DLL_DECL void ProfilerRegisterThread() { ProfileHandlerRegisterThread(); } extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush() { extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush() { CpuProfiler::instance_.FlushTable(); } extern "C" PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads() { extern "C" PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads() { return CpuProfiler::instance_.Enabled(); } extern "C" PERFTOOLS_DLL_DECL int ProfilerStart(const char* fname) { extern "C" PERFTOOLS_DLL_DECL int ProfilerStart(const char *fname) { return CpuProfiler::instance_.Start(fname, NULL); } extern "C" PERFTOOLS_DLL_DECL int ProfilerStartWithOptions( const char *fname, const ProfilerOptions *options) { extern "C" PERFTOOLS_DLL_DECL int ProfilerStartWithOptions(const char *fname, const ProfilerOptions *options) { return CpuProfiler::instance_.Start(fname, options); } extern "C" PERFTOOLS_DLL_DECL void ProfilerStop() { extern "C" PERFTOOLS_DLL_DECL void ProfilerStop() { CpuProfiler::instance_.Stop(); } extern "C" PERFTOOLS_DLL_DECL void ProfilerGetCurrentState( ProfilerState* state) { extern "C" PERFTOOLS_DLL_DECL void ProfilerGetCurrentState(ProfilerState *state) { CpuProfiler::instance_.GetCurrentState(state); } extern "C" PERFTOOLS_DLL_DECL int ProfilerGetStackTrace( void** result, int max_depth, int skip_count, const void *uc) { extern "C" PERFTOOLS_DLL_DECL int ProfilerGetStackTrace(void **result, int max_depth, int skip_count, const void *uc) { return GetStackTraceWithContext(result, max_depth, skip_count, uc); } Loading @@ -410,25 +424,55 @@ extern "C" PERFTOOLS_DLL_DECL int ProfilerGetStackTrace( // work as well for profiling, and also interferes with alarm(). Because of // these issues, unless a specific need is identified, profiler support is // disabled under Cygwin. extern "C" void ProfilerRegisterThread() { } extern "C" void ProfilerFlush() { } extern "C" int ProfilingIsEnabledForAllThreads() { return 0; } extern "C" int ProfilerStart(const char* fname) { return 0; } extern "C" int ProfilerStartWithOptions(const char *fname, const ProfilerOptions *options) { extern "C" void ProfilerRegisterThread() {} extern "C" void ProfilerFlush() {} extern "C" int ProfilingIsEnabledForAllThreads() { return 0; } extern "C" int ProfilerStart(const char *fname) { return 0; } extern "C" void ProfilerStop() { } extern "C" void ProfilerGetCurrentState(ProfilerState* state) { extern "C" int ProfilerStartWithOptions(const char *fname, const ProfilerOptions *options) { return 0; } extern "C" void ProfilerStop() {} extern "C" void ProfilerGetCurrentState(ProfilerState *state) { memset(state, 0, sizeof(*state)); } extern "C" int ProfilerGetStackTrace( void** result, int max_depth, int skip_count, const void *uc) { extern "C" int ProfilerGetStackTrace(void **result, int max_depth, int skip_count, const void *uc) { return 0; } #endif// OS_CYGWIN // DEPRECATED routines extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable() { } extern "C" PERFTOOLS_DLL_DECL void ProfilerDisable() { } extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable() {} extern "C" PERFTOOLS_DLL_DECL void ProfilerDisable() {} src/sled/profiling/internal/remote_gperf_impl.cc 0 → 100644 +32 −0 Original line number Diff line number Diff line #include "remote_gperf_impl.h" #include <gperftools/heap-profiler.h> #include <gperftools/malloc_extension.h> #include <gperftools/profiler.h> namespace sled { RemoteGPerfImpl::RemoteGPerfImpl(int port) {} RemoteGPerfImpl::~RemoteGPerfImpl() {} std::string RemoteGPerfImpl::HeapGET() { MallocExtensionWriter writer; MallocExtension::instance()->GetHeapSample(&writer); return writer; } std::string RemoteGPerfImpl::GrowthGET() { MallocExtensionWriter writer; MallocExtension::instance()->GetHeapGrowthStacks(&writer); return writer; } std::string RemoteGPerfImpl::CmdLineGET() { return ""; } }// namespace sled src/sled/profiling/internal/remote_gperf_impl.h 0 → 100644 +28 −0 Original line number Diff line number Diff line #ifndef SLED_PROFILING_INTERNAL_REMOTE_GPERF_IMPL_H #define SLED_PROFILING_INTERNAL_REMOTE_GPERF_IMPL_H #pragma once #include "sled/buffer.h" namespace sled { class RemoteGPerfImpl { public: RemoteGPerfImpl(int port); ~RemoteGPerfImpl(); private: std::string HeapGET(); std::string GrowthGET(); // 1. read data from /proc/selfcmdline // 2. replace all NULL(\0) by new Lines std::string CmdLineGET(); std::string SymbolGET(); // request: 0x0824d061+0x0824d1cf // response: <hex address><tab><function name> std::string SymbolPOST(const std::string &address); }; }// namespace sled #endif// SLED_PROFILING_INTERNAL_REMOTE_GPERF_IMPL_H src/sled/profiling/remote_gperf.h 0 → 100644 +28 −0 Original line number Diff line number Diff line #ifndef SLED_PROFILING_REMOTE_GPERF_H #define SLED_PROFILING_REMOTE_GPERF_H #pragma once namespace sled { // DOCS: https://gperftools.github.io/gperftools/pprof_remote_servers.html // interface // 1. http://host:80/pprof/heap // 2. http://host:80/pprof/profile // http://host:80/ // http://host:80 // 3. http://host:80/pprof/growth // 4. http://host:80/myservice/pprof/heap // 5. http://host:80/profile/ class RemoteGPerf { public: RemoteGPerf(int port); ~RemoteGPerf(); private: }; }// namespace sled #endif// SLED_PROFILING_REMOTE_GPERF_H src/sled/system/thread_pool_test.cc +12 −0 Original line number Diff line number Diff line #include <random> #include <sled/synchronization/event.h> #include <sled/system/fiber/wait_group.h> #include <sled/system/thread_pool.h> std::random_device rd; Loading Loading @@ -81,4 +82,15 @@ TEST_SUITE("ThreadPool") CHECK(waiter.Wait(sled::TimeDelta::Millis(150))); delete tp; } TEST_CASE("10^6 task test") { sled::ThreadPool *tp = new sled::ThreadPool(); const int task_num = 1E6; sled::WaitGroup wg(task_num); for (int i = 0; i < task_num; i++) { tp->PostTask([wg] { wg.Done(); }); } wg.Wait(); } } Loading
3party/gperftools/src/profiler.cc +298 −254 Original line number Diff line number Diff line Loading @@ -36,10 +36,10 @@ #include "config.h" #include "getpc.h"// should be first to get the _GNU_SOURCE dfn #include <signal.h> #include <assert.h> #include <stdio.h> #include <errno.h> #include <signal.h> #include <stdio.h> #include <string.h> #ifdef HAVE_UNISTD_H #include <unistd.h>// for getpid() Loading @@ -54,17 +54,17 @@ typedef ucontext ucontext_t; #else typedef int ucontext_t;// just to quiet the compiler, mostly #endif #include <sys/time.h> #include <string> #include <gperftools/profiler.h> #include <gperftools/stacktrace.h> #include "base/commandlineflags.h" #include "base/logging.h" #include "base/googleinit.h" #include "base/logging.h" #include "base/spinlock.h" #include "base/sysinfo.h" /* for GetUniquePathFromEnv, etc */ #include "profiledata.h" #include "profile-handler.h" #include "profiledata.h" #include <gperftools/profiler.h> #include <gperftools/stacktrace.h> #include <string> #include <sys/time.h> using std::string; Loading Loading @@ -133,13 +133,13 @@ class CpuProfiler { void DisableHandler(); // Signal handler that records the interrupted pc in the profile data. static void prof_handler(int sig, siginfo_t*, void* signal_ucontext, void* cpu_profiler); static void prof_handler(int sig, siginfo_t *, void *signal_ucontext, void *cpu_profiler); }; // Signal handler that is registered when a user selectable signal // number is defined in the environment variable CPUPROFILESIGNAL. static void CpuProfilerSwitch(int signal_number) static void CpuProfilerSwitch(int signal_number) { static unsigned profile_count; static char base_profile_name[PATH_MAX]; Loading @@ -152,18 +152,17 @@ static void CpuProfilerSwitch(int signal_number) } } if (!started) { char full_profile_name[PATH_MAX + 16]; snprintf(full_profile_name, sizeof(full_profile_name), "%s.%u", base_profile_name, profile_count++); snprintf(full_profile_name, sizeof(full_profile_name), "%s.%u", base_profile_name, profile_count); if (!started) { ++profile_count; if (!ProfilerStart(full_profile_name)) { RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n", full_profile_name, strerror(errno)); RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n", full_profile_name, strerror(errno)); } RAW_LOG(INFO, "Start New cpu Profiling for '%s'", full_profile_name); } else { ProfilerStop(); RAW_LOG(INFO, "Stop cpu Profiling for '%s'", full_profile_name); } started = !started; } Loading @@ -174,8 +173,8 @@ static void CpuProfilerSwitch(int signal_number) CpuProfiler CpuProfiler::instance_; // Initialize profiling: activated if getenv("CPUPROFILE") exists. CpuProfiler::CpuProfiler() : prof_handler_token_(NULL) { CpuProfiler::CpuProfiler() : prof_handler_token_(NULL) { // TODO(cgd) Move this code *out* of the CpuProfile constructor into a // separate object responsible for initialization. With ProfileHandler there // is no need to limit the number of profilers. Loading Loading @@ -219,27 +218,24 @@ CpuProfiler::CpuProfiler() } if (!Start(fname, NULL)) { RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n", fname, strerror(errno)); RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n", fname, strerror(errno)); } } } bool CpuProfiler::Start(const char* fname, const ProfilerOptions* options) { bool CpuProfiler::Start(const char *fname, const ProfilerOptions *options) { SpinLockHolder cl(&lock_); if (collector_.enabled()) { return false; } if (collector_.enabled()) { return false; } ProfileHandlerState prof_handler_state; ProfileHandlerGetState(&prof_handler_state); ProfileData::Options collector_options; collector_options.set_frequency(prof_handler_state.frequency); if (!collector_.Start(fname, collector_options)) { return false; } if (!collector_.Start(fname, collector_options)) { return false; } filter_ = NULL; if (options != NULL && options->filter_in_thread != NULL) { Loading @@ -253,17 +249,15 @@ bool CpuProfiler::Start(const char* fname, const ProfilerOptions* options) { return true; } CpuProfiler::~CpuProfiler() { Stop(); } CpuProfiler::~CpuProfiler() { Stop(); } // Stop profiling and write out any collected profile data void CpuProfiler::Stop() { void CpuProfiler::Stop() { SpinLockHolder cl(&lock_); if (!collector_.enabled()) { return; } if (!collector_.enabled()) { return; } // Unregister prof_handler to stop receiving SIGPROF interrupts before // stopping the collector. Loading @@ -274,12 +268,12 @@ void CpuProfiler::Stop() { collector_.Stop(); } void CpuProfiler::FlushTable() { void CpuProfiler::FlushTable() { SpinLockHolder cl(&lock_); if (!collector_.enabled()) { return; } if (!collector_.enabled()) { return; } // Unregister prof_handler to stop receiving SIGPROF interrupts before // flushing the profile data. Loading @@ -292,12 +286,16 @@ void CpuProfiler::FlushTable() { EnableHandler(); } bool CpuProfiler::Enabled() { bool CpuProfiler::Enabled() { SpinLockHolder cl(&lock_); return collector_.enabled(); } void CpuProfiler::GetCurrentState(ProfilerState* state) { void CpuProfiler::GetCurrentState(ProfilerState *state) { ProfileData::State collector_state; { SpinLockHolder cl(&lock_); Loading @@ -312,13 +310,17 @@ void CpuProfiler::GetCurrentState(ProfilerState* state) { state->profile_name[buf_size - 1] = '\0'; } void CpuProfiler::EnableHandler() { void CpuProfiler::EnableHandler() { RAW_CHECK(prof_handler_token_ == NULL, "SIGPROF handler already registered"); prof_handler_token_ = ProfileHandlerRegisterCallback(prof_handler, this); RAW_CHECK(prof_handler_token_ != NULL, "Failed to set up SIGPROF handler"); } void CpuProfiler::DisableHandler() { void CpuProfiler::DisableHandler() { RAW_CHECK(prof_handler_token_ != NULL, "SIGPROF handler is not registered"); ProfileHandlerUnregisterCallback(prof_handler_token_); prof_handler_token_ = NULL; Loading @@ -330,12 +332,12 @@ void CpuProfiler::DisableHandler() { // access the data touched by prof_handler() disable this signal handler before // accessing the data and therefore cannot execute concurrently with // prof_handler(). void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext, void* cpu_profiler) { void CpuProfiler::prof_handler(int sig, siginfo_t *, void *signal_ucontext, void *cpu_profiler) { CpuProfiler *instance = static_cast<CpuProfiler *>(cpu_profiler); if (instance->filter_ == NULL || (*instance->filter_)(instance->filter_arg_)) { if (instance->filter_ == NULL || (*instance->filter_)(instance->filter_arg_)) { void *stack[ProfileData::kMaxStackDepth]; // Under frame-pointer-based unwinding at least on x86, the Loading @@ -350,8 +352,7 @@ void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext, // "pprof" at analysis time. Instead of skipping the top frames, // we could skip nothing, but that would increase the profile size // unnecessarily. int depth = GetStackTraceWithContext(stack + 1, arraysize(stack) - 1, 3, signal_ucontext); int depth = GetStackTraceWithContext(stack + 1, arraysize(stack) - 1, 3, signal_ucontext); void **used_stack; if (depth > 0 && stack[1] == stack[0]) { Loading @@ -369,38 +370,51 @@ void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext, #if !(defined(__CYGWIN__) || defined(__CYGWIN32__)) extern "C" PERFTOOLS_DLL_DECL void ProfilerRegisterThread() { extern "C" PERFTOOLS_DLL_DECL void ProfilerRegisterThread() { ProfileHandlerRegisterThread(); } extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush() { extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush() { CpuProfiler::instance_.FlushTable(); } extern "C" PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads() { extern "C" PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads() { return CpuProfiler::instance_.Enabled(); } extern "C" PERFTOOLS_DLL_DECL int ProfilerStart(const char* fname) { extern "C" PERFTOOLS_DLL_DECL int ProfilerStart(const char *fname) { return CpuProfiler::instance_.Start(fname, NULL); } extern "C" PERFTOOLS_DLL_DECL int ProfilerStartWithOptions( const char *fname, const ProfilerOptions *options) { extern "C" PERFTOOLS_DLL_DECL int ProfilerStartWithOptions(const char *fname, const ProfilerOptions *options) { return CpuProfiler::instance_.Start(fname, options); } extern "C" PERFTOOLS_DLL_DECL void ProfilerStop() { extern "C" PERFTOOLS_DLL_DECL void ProfilerStop() { CpuProfiler::instance_.Stop(); } extern "C" PERFTOOLS_DLL_DECL void ProfilerGetCurrentState( ProfilerState* state) { extern "C" PERFTOOLS_DLL_DECL void ProfilerGetCurrentState(ProfilerState *state) { CpuProfiler::instance_.GetCurrentState(state); } extern "C" PERFTOOLS_DLL_DECL int ProfilerGetStackTrace( void** result, int max_depth, int skip_count, const void *uc) { extern "C" PERFTOOLS_DLL_DECL int ProfilerGetStackTrace(void **result, int max_depth, int skip_count, const void *uc) { return GetStackTraceWithContext(result, max_depth, skip_count, uc); } Loading @@ -410,25 +424,55 @@ extern "C" PERFTOOLS_DLL_DECL int ProfilerGetStackTrace( // work as well for profiling, and also interferes with alarm(). Because of // these issues, unless a specific need is identified, profiler support is // disabled under Cygwin. extern "C" void ProfilerRegisterThread() { } extern "C" void ProfilerFlush() { } extern "C" int ProfilingIsEnabledForAllThreads() { return 0; } extern "C" int ProfilerStart(const char* fname) { return 0; } extern "C" int ProfilerStartWithOptions(const char *fname, const ProfilerOptions *options) { extern "C" void ProfilerRegisterThread() {} extern "C" void ProfilerFlush() {} extern "C" int ProfilingIsEnabledForAllThreads() { return 0; } extern "C" int ProfilerStart(const char *fname) { return 0; } extern "C" void ProfilerStop() { } extern "C" void ProfilerGetCurrentState(ProfilerState* state) { extern "C" int ProfilerStartWithOptions(const char *fname, const ProfilerOptions *options) { return 0; } extern "C" void ProfilerStop() {} extern "C" void ProfilerGetCurrentState(ProfilerState *state) { memset(state, 0, sizeof(*state)); } extern "C" int ProfilerGetStackTrace( void** result, int max_depth, int skip_count, const void *uc) { extern "C" int ProfilerGetStackTrace(void **result, int max_depth, int skip_count, const void *uc) { return 0; } #endif// OS_CYGWIN // DEPRECATED routines extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable() { } extern "C" PERFTOOLS_DLL_DECL void ProfilerDisable() { } extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable() {} extern "C" PERFTOOLS_DLL_DECL void ProfilerDisable() {}
src/sled/profiling/internal/remote_gperf_impl.cc 0 → 100644 +32 −0 Original line number Diff line number Diff line #include "remote_gperf_impl.h" #include <gperftools/heap-profiler.h> #include <gperftools/malloc_extension.h> #include <gperftools/profiler.h> namespace sled { RemoteGPerfImpl::RemoteGPerfImpl(int port) {} RemoteGPerfImpl::~RemoteGPerfImpl() {} std::string RemoteGPerfImpl::HeapGET() { MallocExtensionWriter writer; MallocExtension::instance()->GetHeapSample(&writer); return writer; } std::string RemoteGPerfImpl::GrowthGET() { MallocExtensionWriter writer; MallocExtension::instance()->GetHeapGrowthStacks(&writer); return writer; } std::string RemoteGPerfImpl::CmdLineGET() { return ""; } }// namespace sled
src/sled/profiling/internal/remote_gperf_impl.h 0 → 100644 +28 −0 Original line number Diff line number Diff line #ifndef SLED_PROFILING_INTERNAL_REMOTE_GPERF_IMPL_H #define SLED_PROFILING_INTERNAL_REMOTE_GPERF_IMPL_H #pragma once #include "sled/buffer.h" namespace sled { class RemoteGPerfImpl { public: RemoteGPerfImpl(int port); ~RemoteGPerfImpl(); private: std::string HeapGET(); std::string GrowthGET(); // 1. read data from /proc/selfcmdline // 2. replace all NULL(\0) by new Lines std::string CmdLineGET(); std::string SymbolGET(); // request: 0x0824d061+0x0824d1cf // response: <hex address><tab><function name> std::string SymbolPOST(const std::string &address); }; }// namespace sled #endif// SLED_PROFILING_INTERNAL_REMOTE_GPERF_IMPL_H
src/sled/profiling/remote_gperf.h 0 → 100644 +28 −0 Original line number Diff line number Diff line #ifndef SLED_PROFILING_REMOTE_GPERF_H #define SLED_PROFILING_REMOTE_GPERF_H #pragma once namespace sled { // DOCS: https://gperftools.github.io/gperftools/pprof_remote_servers.html // interface // 1. http://host:80/pprof/heap // 2. http://host:80/pprof/profile // http://host:80/ // http://host:80 // 3. http://host:80/pprof/growth // 4. http://host:80/myservice/pprof/heap // 5. http://host:80/profile/ class RemoteGPerf { public: RemoteGPerf(int port); ~RemoteGPerf(); private: }; }// namespace sled #endif// SLED_PROFILING_REMOTE_GPERF_H
src/sled/system/thread_pool_test.cc +12 −0 Original line number Diff line number Diff line #include <random> #include <sled/synchronization/event.h> #include <sled/system/fiber/wait_group.h> #include <sled/system/thread_pool.h> std::random_device rd; Loading Loading @@ -81,4 +82,15 @@ TEST_SUITE("ThreadPool") CHECK(waiter.Wait(sled::TimeDelta::Millis(150))); delete tp; } TEST_CASE("10^6 task test") { sled::ThreadPool *tp = new sled::ThreadPool(); const int task_num = 1E6; sled::WaitGroup wg(task_num); for (int i = 0; i < task_num; i++) { tp->PostTask([wg] { wg.Done(); }); } wg.Wait(); } }