Skip to content

Commit d77d5af

Browse files
committed
ITS: optional stacktraces from allocations
1 parent e009f56 commit d77d5af

File tree

1 file changed

+51
-3
lines changed

1 file changed

+51
-3
lines changed

Detectors/ITSMFT/ITS/tracking/include/ITStracking/BoundedAllocator.h

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,20 @@
2323
#include <vector>
2424
#include <exception>
2525

26+
#define ITS_TRACKMEMORY
27+
// #define ITS_TRACKMEMORYTRACE
28+
29+
#ifdef ITS_TRACKMEMORYTRACE
30+
#include <execinfo.h>
31+
#include <unistd.h>
32+
#include <fstream>
33+
#endif
34+
2635
#include "GPUCommonLogger.h"
2736

2837
namespace o2::its
2938
{
3039

31-
// #define ITS_TRACKMEMORY
32-
3340
class BoundedMemoryResource final : public std::pmr::memory_resource
3441
{
3542
public:
@@ -75,6 +82,9 @@ class BoundedMemoryResource final : public std::pmr::memory_resource
7582
#ifdef ITS_TRACKMEMORY
7683
++mCountAllocate;
7784
#endif
85+
86+
logStackTrace<true>(bytes);
87+
7888
return mUpstream->allocate(bytes, alignment);
7989
}
8090

@@ -83,6 +93,7 @@ class BoundedMemoryResource final : public std::pmr::memory_resource
8393
#ifdef ITS_TRACKMEMORY
8494
++mCountDeallocate;
8595
#endif
96+
logStackTrace<false>(bytes);
8697
mUpstream->deallocate(p, bytes, alignment);
8798
mUsedMemory.fetch_sub(bytes, std::memory_order_relaxed);
8899
}
@@ -124,11 +135,48 @@ class BoundedMemoryResource final : public std::pmr::memory_resource
124135
size_t mMaxMemory{std::numeric_limits<size_t>::max()};
125136
std::atomic<size_t> mCountThrow{0};
126137
std::atomic<size_t> mUsedMemory{0};
138+
std::pmr::memory_resource* mUpstream;
139+
127140
#ifdef ITS_TRACKMEMORY
128141
std::atomic<size_t> mCountAllocate{0};
129142
std::atomic<size_t> mCountDeallocate{0};
130143
#endif
131-
std::pmr::memory_resource* mUpstream;
144+
#ifdef ITS_TRACKMEMORYTRACE
145+
inline uint64_t currentMicros()
146+
{
147+
auto now = std::chrono::high_resolution_clock::now();
148+
return std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch()).count();
149+
}
150+
std::ofstream mTraceFile{"stacktraces", std::ios::app}; // Appending mode
151+
size_t mAllocId{0}; // Only for tracking
152+
std::mutex mFileMutex;
153+
154+
template <bool isAlloc>
155+
void logStackTrace(size_t bytes)
156+
{
157+
constexpr int maxFrames = 64;
158+
void* frames[maxFrames];
159+
int frameCount = backtrace(frames, maxFrames);
160+
char** symbols = backtrace_symbols(frames, frameCount);
161+
if (!symbols)
162+
return;
163+
164+
std::lock_guard<std::mutex> lock(mFileMutex);
165+
mTraceFile << ((isAlloc) ? "#ALLOC " : "#DEALLOC ") << mAllocId++ << " SIZE " << bytes << " TIME " << currentMicros() << '\n';
166+
for (int i = 0; i < frameCount; ++i) {
167+
mTraceFile << symbols[i] << "\n";
168+
}
169+
mTraceFile << "#END\n";
170+
mTraceFile.flush(); // Flush for crash-safe logging
171+
172+
free(symbols);
173+
}
174+
#else
175+
template <bool isAlloc>
176+
void logStackTrace(size_t)
177+
{
178+
}
179+
#endif
132180
};
133181

134182
template <typename T>

0 commit comments

Comments
 (0)