mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 00:22:29 +00:00
a10aa9ad50
libunwind is reentrant and signal safe, and works faster then then gcc_eh (plus it has some custom patches for problems that have been found during it's usage in ClickHouse). gcc_eh may be missing in the system (if gcc was not installed), and even if it exists clickhouse uses -nodefaultlibs, so some care should be made to make it work. Also this library is tiny and there shouln't be any problem to require it always (there is already tendency to require some contrib libraries, i.e. poco). Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
90 lines
1.9 KiB
C++
90 lines
1.9 KiB
C++
#pragma once
|
|
|
|
#include <optional>
|
|
#include <base/types.h>
|
|
#include <signal.h>
|
|
#include <time.h>
|
|
|
|
#include "config.h"
|
|
|
|
|
|
namespace Poco
|
|
{
|
|
class Logger;
|
|
}
|
|
|
|
namespace DB
|
|
{
|
|
|
|
/**
|
|
* Query profiler implementation for selected thread.
|
|
*
|
|
* This class installs timer and signal handler on creation to:
|
|
* 1. periodically pause given thread
|
|
* 2. collect thread's current stack trace
|
|
* 3. write collected stack trace to trace_pipe for TraceCollector
|
|
*
|
|
* Destructor tries to unset timer and restore previous signal handler.
|
|
* Note that signal handler implementation is defined by template parameter. See QueryProfilerReal and QueryProfilerCPU.
|
|
*/
|
|
|
|
#ifndef __APPLE__
|
|
class Timer
|
|
{
|
|
public:
|
|
Timer();
|
|
Timer(const Timer &) = delete;
|
|
Timer & operator = (const Timer &) = delete;
|
|
~Timer();
|
|
|
|
void createIfNecessary(UInt64 thread_id, int clock_type, int pause_signal);
|
|
void set(UInt32 period);
|
|
void stop();
|
|
void cleanup();
|
|
|
|
private:
|
|
Poco::Logger * log;
|
|
std::optional<timer_t> timer_id;
|
|
};
|
|
#endif
|
|
|
|
template <typename ProfilerImpl>
|
|
class QueryProfilerBase
|
|
{
|
|
public:
|
|
QueryProfilerBase(UInt64 thread_id, int clock_type, UInt32 period, int pause_signal_);
|
|
~QueryProfilerBase();
|
|
|
|
private:
|
|
void cleanup();
|
|
|
|
Poco::Logger * log;
|
|
|
|
#ifndef __APPLE__
|
|
inline static thread_local Timer timer = Timer();
|
|
#endif
|
|
|
|
/// Pause signal to interrupt threads to get traces
|
|
int pause_signal;
|
|
};
|
|
|
|
/// Query profiler with timer based on real clock
|
|
class QueryProfilerReal : public QueryProfilerBase<QueryProfilerReal>
|
|
{
|
|
public:
|
|
QueryProfilerReal(UInt64 thread_id, UInt32 period); /// NOLINT
|
|
|
|
static void signalHandler(int sig, siginfo_t * info, void * context);
|
|
};
|
|
|
|
/// Query profiler with timer based on CPU clock
|
|
class QueryProfilerCPU : public QueryProfilerBase<QueryProfilerCPU>
|
|
{
|
|
public:
|
|
QueryProfilerCPU(UInt64 thread_id, UInt32 period); /// NOLINT
|
|
|
|
static void signalHandler(int sig, siginfo_t * info, void * context);
|
|
};
|
|
|
|
}
|