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
2837namespace o2 ::its
2938{
3039
31- // #define ITS_TRACKMEMORY
32-
3340class 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
134182template <typename T>
0 commit comments