From 04efc6ffcb2e26ccc1e3878f3fea9249fca56eec Mon Sep 17 00:00:00 2001 From: Bright Chen Date: Mon, 11 Mar 2024 23:26:33 +0800 Subject: [PATCH] Add comments --- src/bthread/mutex.cpp | 2 +- src/butil/iobuf_profiler.cpp | 23 ++++++++++++++++------- src/butil/iobuf_profiler.h | 21 +++++++++++++-------- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/bthread/mutex.cpp b/src/bthread/mutex.cpp index b4008fd796..d22c8753e1 100644 --- a/src/bthread/mutex.cpp +++ b/src/bthread/mutex.cpp @@ -268,7 +268,7 @@ BAIDU_CACHELINE_ALIGNMENT static ContentionProfiler* g_cp = NULL; // Need this version to solve an issue that non-empty entries left by // previous contention profilers should be detected and overwritten. static uint64_t g_cp_version = 0; -// Protecting accesss to g_cp. +// Protecting accesses to g_cp. static pthread_mutex_t g_cp_mutex = PTHREAD_MUTEX_INITIALIZER; // The map storing information for profiling pthread_mutex. Different from diff --git a/src/butil/iobuf_profiler.cpp b/src/butil/iobuf_profiler.cpp index 8887817489..bcb5339130 100644 --- a/src/butil/iobuf_profiler.cpp +++ b/src/butil/iobuf_profiler.cpp @@ -32,12 +32,24 @@ namespace iobuf { extern void* cp(void *__restrict dest, const void *__restrict src, size_t n); } +// Max and min sleep time for IOBuf profiler consuming thread +// when `_sample_queue' is empty. +const uint32_t IOBufProfiler::MIN_SLEEP_MS = 10; +const uint32_t IOBufProfiler::MAX_SLEEP_MS = 1000; + static pthread_once_t g_iobuf_profiler_info_once = PTHREAD_ONCE_INIT; static bool g_iobuf_profiler_enabled = false; static uint g_iobuf_profiler_sample_rate = 100; + +// Environment variables: +// 1. ENABLE_IOBUF_PROFILER: set value to 1 to enable IOBuf profiler. +// 2. IOBUF_PROFILER_SAMPLE_RATE: set value between (0, 100] to control sample rate. static void InitGlobalIOBufProfilerInfo() { const char* enabled = getenv("ENABLE_IOBUF_PROFILER"); g_iobuf_profiler_enabled = enabled && strcmp("1", enabled) == 0 && ::GetStackTrace != NULL; + if (g_iobuf_profiler_enabled) { + return; + } char* rate = getenv("IOBUF_PROFILER_SAMPLE_RATE"); if (rate) { @@ -68,8 +80,6 @@ bool IsIOBufProfilerSamplable() { return fast_rand_less_than(100) + 1 <= g_iobuf_profiler_sample_rate; } -IOBufSample* const IOBufSample::UNCONNECTED = (IOBufSample*)(intptr_t)-1; - size_t IOBufSample::stack_hash_code() const { if (nframes == 0) { return 0; @@ -81,9 +91,6 @@ size_t IOBufSample::stack_hash_code() const { return _hash_code; } -const uint32_t IOBufProfiler::MIN_SLEEP_MS = 10; -const uint32_t IOBufProfiler::MAX_SLEEP_MS = 1000; - IOBufProfiler* IOBufProfiler::GetInstance() { return ::Singleton>::get(); } @@ -200,6 +207,8 @@ void IOBufProfiler::Flush2Disk(const char* filename) { } _disk_buf.append(os.buf().movable()); + // Append /proc/self/maps to the end of the contention file, required by + // pprof.pl, otherwise the functions in sys libs are not interpreted. butil::IOPortal mem_maps; const butil::fd_guard maps_fd(open("/proc/self/maps", O_RDONLY)); if (maps_fd >= 0) { @@ -274,8 +283,8 @@ void IOBufProfiler::Consume() { is_empty = false; } - _sleep_ms = !is_empty ? - MIN_SLEEP_MS : + // If `_sample_queue' is empty, exponential increase in sleep time. + _sleep_ms = !is_empty ? MIN_SLEEP_MS : std::min(_sleep_ms * 2, MAX_SLEEP_MS); } diff --git a/src/butil/iobuf_profiler.h b/src/butil/iobuf_profiler.h index 5a10064bfd..7178f20a7b 100644 --- a/src/butil/iobuf_profiler.h +++ b/src/butil/iobuf_profiler.h @@ -34,8 +34,6 @@ struct IOBufSample; typedef std::shared_ptr IOBufRefSampleSharedPtr; struct IOBufSample { - static IOBufSample* const UNCONNECTED; - IOBufSample* next; IOBuf::Block* block; int64_t count; // // reference count of the block. @@ -105,10 +103,11 @@ class IOBufProfiler : public butil::SimpleThread { public: static IOBufProfiler* GetInstance(); + // Submit the IOBuf sample along with stacktrace. void Submit(IOBufSample* s); - + // Dump IOBuf sample to map. void Dump(IOBufSample* s); - + // Write buffered data into resulting file. void Flush2Disk(const char* filename); void StopAndJoin(); @@ -137,17 +136,23 @@ class IOBufProfiler : public butil::SimpleThread { DISALLOW_COPY_AND_ASSIGN(IOBufProfiler); void Run() override; - + // Consume the IOBuf sample in _sample_queue. void Consume(); + // Stop flag of IOBufProfiler. butil::atomic _stop; + // IOBuf sample queue. MPSCQueue _sample_queue; - butil::IOBuf _disk_buf; // temp buf before saving the file. - IOBufRefMap _stack_map; // combining same samples to make result smaller. - BlockInfoMap _block_info_map; // record block info + // Temp buf before saving the file. + butil::IOBuf _disk_buf; + // Combining same samples to make result smaller. + IOBufRefMap _stack_map; + // Record block info. + BlockInfoMap _block_info_map; Mutex _mutex; + // Sleep when `_sample_queue' is empty. uint32_t _sleep_ms; static const uint32_t MIN_SLEEP_MS; static const uint32_t MAX_SLEEP_MS;