Skip to content

Commit 3da7a47

Browse files
author
nitrocaster
committed
Refactor memory statistic collector.
1 parent 2ee6591 commit 3da7a47

File tree

1 file changed

+65
-93
lines changed

1 file changed

+65
-93
lines changed
Lines changed: 65 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,131 +1,103 @@
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

Comments
 (0)