11#include " stdafx.h"
2- #include " xrCore.h"
32
4- #ifdef DEBUG_MEMORY_MANAGER
5- # pragma warning(push)
6- # pragma warning(disable:4995)
7- # include < malloc.h>
8- # pragma warning(pop)
3+ #ifndef DEBUG_MEMORY_MANAGER
4+ #include < malloc.h> // _alloca
95
10- static bool g_mem_alloc_gather_stats = false ;
11- static float g_mem_alloc_gather_stats_frequency = 0 .f;
12-
13- typedef std::pair<PSTR,u32 > STATS_PAIR;
14- typedef std::multimap<u32 ,STATS_PAIR> STATS;
15- static STATS stats;
16-
17- void mem_alloc_gather_stats (const bool & value)
6+ namespace
187{
19- g_mem_alloc_gather_stats = value;
8+ bool StatsGatherEnabled = false ;
9+ float StatsGatherFrequency = 0 .0f ;
10+ StackTraceInfo StackTrace;
2011}
2112
22- void mem_alloc_gather_stats_frequency ( const float & value)
13+ struct StatsItem
2314{
24- g_mem_alloc_gather_stats_frequency = value;
25- }
15+ char *StackTrace;
16+ size_t Calls;
17+ };
2618
27- void mem_alloc_show_stats ()
28- {
29- u32 size = (u32 )stats.size ();
30- STATS_PAIR* strings = (STATS_PAIR*)_alloca (size*sizeof (STATS_PAIR));
31- STATS_PAIR* e = strings + size;
32- STATS_PAIR* i = strings;
19+ static std::multimap<u32 , StatsItem> stats;
20+
21+ void mem_alloc_gather_stats (const bool &value)
22+ { StatsGatherEnabled = value; }
23+
24+ void mem_alloc_gather_stats_frequency (const float &value)
25+ { StatsGatherFrequency = value; }
3326
34- u32 accumulator = 0 ;
35- STATS::const_iterator I = stats.begin ();
36- STATS::const_iterator E = stats.end ();
37- for ( ; I != E; ++I, ++i)
27+ void mem_alloc_show_stats ()
28+ {
29+ size_t statsSize = stats.size ();
30+ auto strings = (StatsItem *)malloc (statsSize*sizeof (StatsItem));
31+ size_t totalCalls = 0 , i = 0 ;
32+ for (auto &pair : stats)
3833 {
39- *i = (*I).second ;
40- accumulator += (*I).second .second ;
34+ strings[i] = pair.second ;
35+ i++;
36+ totalCalls += pair.second .Calls ;
4137 }
42-
43- struct predicate
38+ struct Comparer
4439 {
45- static inline bool compare (const STATS_PAIR& _0, const STATS_PAIR& _1)
46- {
47- return (_0.second < _1.second );
48- }
40+ bool operator ()(const StatsItem &a, const StatsItem &b)
41+ { return a.Calls <b.Calls ; }
4942 };
50-
51- std::sort (strings,e,predicate::compare);
52-
53- int j = 0 ;
54- for (i = strings; i != e; ++i, ++j)
43+ std::sort (strings, strings+statsSize, Comparer ());
44+ for (i = 0 ; i<statsSize; i++)
5545 {
56- Msg (" %d(%d)-----------------%d[%d]:%5.2f%%------------------" ,j,size,(*i).second ,accumulator,((*i).second *100 )/float (accumulator));
57- Log ((*i).first );
46+ StatsItem &item = strings[i];
47+ Msg (" %zu(%zu)-----------------%zu[%zu]:%5.2f%%------------------" ,
48+ i, statsSize, item.Calls , totalCalls, item.Calls *100 /float (totalCalls));
49+ Log (item.StackTrace );
5850 }
51+ free (strings);
5952}
6053
61- void mem_alloc_clear_stats ()
54+ void mem_alloc_clear_stats ()
6255{
63- STATS::iterator I = stats.begin ();
64- STATS::iterator E = stats.end ();
65- for ( ; I != E; ++I)
66- free ((*I).second .first );
67-
68- stats.clear ();
56+ for (auto &item : stats)
57+ free (item.second .StackTrace );
58+ stats.clear ();
6959}
7060
71- namespace
61+ __declspec (noinline) void save_stack_trace()
7262{
73- StackTraceInfo StackTrace;
74- }
75-
76- __declspec (noinline)
77- void save_stack_trace ()
78- {
79- if (!g_mem_alloc_gather_stats)
63+ if (!StatsGatherEnabled)
8064 return ;
81-
82- if (::Random.randF () >= g_mem_alloc_gather_stats_frequency)
65+ if (::Random.randF ()>=StatsGatherFrequency)
8366 return ;
84-
85- // OutputDebugStackTrace ("----------------------------------------------------");
8667 StackTrace.Count = xrDebug::BuildStackTrace (StackTrace.Frames , StackTrace.Capacity , StackTrace.LineCapacity );
87- const int skipFrames = 2 ;
68+ const size_t skipFrames = 2 ;
8869 if (StackTrace.Count <=skipFrames)
8970 return ;
90- u32 accumulator = 0 ;
91- int * lengths = (int *)_alloca ((StackTrace.Count -skipFrames)*sizeof (int ));
71+ size_t frameCount = StackTrace.Count -skipFrames;
72+ size_t totalSize = 0 ;
73+ auto lengths = (size_t *)_alloca (frameCount*sizeof (size_t ));
74+ for (int i = 0 ; i<frameCount; i++)
9275 {
93- int * I = lengths;
94- for (int i = skipFrames; i<StackTrace.Count ; ++i, ++I)
95- {
96- *I = xr_strlen (StackTrace[i]);
97- accumulator += u32 (*I+1 );
98- }
76+ lengths[i] = strlen (StackTrace[i+skipFrames]);
77+ totalSize += lengths[i]+1 ;
9978 }
100-
101- PSTR string = (PSTR)malloc (accumulator);
79+ char *stackTrace = (char *)malloc (totalSize);
10280 {
103- PSTR J = string;
104- int * I = lengths;
105- for (int i = skipFrames; i<StackTrace.Count ; ++i, ++I, ++J)
81+ char *ptr = stackTrace;
82+ for (int i = 0 ; i<frameCount; i++)
10683 {
107- memcpy (J , StackTrace[i], *I );
108- J += *I ;
109- *J = ' \n ' ;
84+ memcpy (ptr , StackTrace[i], lengths[i] );
85+ ptr += lengths[i] ;
86+ *ptr = ' \n ' ;
11087 }
111- *--J = 0 ;
88+ *ptr = 0 ;
11289 }
113-
114- u32 crc = crc32 (string, accumulator);
115- STATS::iterator I = stats.find (crc);
116- STATS::iterator E = stats.end ();
117- for ( ; I != E; ++I)
90+ u32 crc = crc32 (stackTrace, totalSize);
91+ for (auto it = stats.find (crc); it!=stats.end (); it++)
11892 {
119- if ((*I).first != crc)
93+ auto &pair = *it;
94+ if (pair.first !=crc)
12095 break ;
121-
122- if (xr_strcmp ((*I).second .first ,string))
96+ if (strcmp (pair.second .StackTrace , stackTrace))
12397 continue ;
124-
125- ++((*I).second .second );
98+ pair.second .Calls ++;
12699 return ;
127100 }
128-
129- stats.insert (std::make_pair (crc, std::make_pair (string, 1 )));
101+ stats.insert ({crc, {stackTrace, 1 }});
130102}
131- #endif // DEBUG
103+ #endif // DEBUG_MEMORY_MANAGER
0 commit comments