PassengerStatistics/Tools/LeakTracer/MemoryAllocationStackTracer.h

125 lines
3.4 KiB
C
Raw Normal View History

2024-03-23 11:57:23 +08:00
#ifndef __MEMORYALLOCATIONSTACKTRACER_H__
#define __MEMORYALLOCATIONSTACKTRACER_H__
#include <boost/stacktrace/stacktrace.hpp>
2024-03-25 00:09:33 +08:00
#include <chrono>
#include <thread>
2024-03-23 11:57:23 +08:00
#include <unordered_map>
extern "C" {
extern void *__real_malloc(size_t size);
extern void __real_free(void *__ptr);
}
template <class T>
class DebugAllocator {
public:
using value_type = T;
using pointer = T *;
typedef const T *const_pointer;
typedef T &reference;
typedef const T &const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
template <class U>
struct rebind {
typedef DebugAllocator<U> other;
};
DebugAllocator() {
}
template <class U>
DebugAllocator(const DebugAllocator<U> &other) noexcept {
}
T *allocate(std::size_t n) {
2024-03-25 00:09:33 +08:00
return reinterpret_cast<T *>(__real_malloc(n * sizeof(T)));
2024-03-23 11:57:23 +08:00
}
void deallocate(T *p, std::size_t n) {
__real_free(p);
}
template <class U, class... Args>
void construct(U *p, Args &&...args) {
::new ((void *)p) U(std::forward<Args>(args)...);
}
template <class U>
void destroy(U *p) {
p->~U();
}
pointer address(reference x) {
return (pointer)&x;
}
const_pointer address(const_reference x) {
return (const_pointer)&x;
}
};
class MemoryAllocationStackTracer {
public:
2024-03-25 00:09:33 +08:00
using Frame = boost::stacktrace::basic_stacktrace<DebugAllocator<boost::stacktrace::frame>>;
using String = std::basic_string<char, std::char_traits<char>, DebugAllocator<char>>;
using OutStringStream = std::basic_ostringstream<char, std::char_traits<char>, DebugAllocator<char>>;
2024-03-25 00:09:33 +08:00
class Infomation {
public:
std::chrono::system_clock::time_point time;
Frame frame;
};
~MemoryAllocationStackTracer();
2024-03-23 11:57:23 +08:00
static MemoryAllocationStackTracer *instance();
2024-03-25 00:09:33 +08:00
inline bool enabled() const {
return m_enabled;
}
template <class Rep, class Period>
void start(const std::string &path, const std::string &applicationName,
const std::chrono::duration<Rep, Period> &intervals) {
if (m_exit) {
m_exit = false;
m_thread = std::thread(&MemoryAllocationStackTracer::run, this);
}
m_intervals = std::chrono::duration_cast<std::chrono::milliseconds>(intervals);
if (!m_enabled) {
m_enabled = true;
}
m_path = path;
m_applicationName = applicationName;
}
void stop();
std::string dump();
2024-03-25 00:09:33 +08:00
void push(uint64_t address, Frame &&stacktrace);
2024-03-23 11:57:23 +08:00
void pop(uint64_t address);
protected:
void run();
2024-03-23 11:57:23 +08:00
private:
2024-03-25 00:09:33 +08:00
std::unordered_map<uint64_t, Infomation, std::hash<uint64_t>, std::equal_to<uint64_t>,
DebugAllocator<std::pair<const uint64_t, Infomation>>>
2024-03-23 11:57:23 +08:00
m_stacktraces;
std::unordered_map<boost::stacktrace::frame::native_frame_ptr_t, uint32_t,
std::hash<boost::stacktrace::frame::native_frame_ptr_t>,
std::equal_to<boost::stacktrace::frame::native_frame_ptr_t>,
DebugAllocator<std::pair<const boost::stacktrace::frame::native_frame_ptr_t, uint32_t>>>
m_counts;
2024-03-23 11:57:23 +08:00
static MemoryAllocationStackTracer *m_instance;
std::string m_path;
std::string m_applicationName;
bool m_exit = true;
std::thread m_thread;
std::chrono::milliseconds m_intervals;
2024-03-25 00:09:33 +08:00
bool m_enabled = false;
2024-03-23 11:57:23 +08:00
};
#endif // __MEMORYALLOCATIONSTACKTRACER_H__