Skip to content

Commit 235e801

Browse files
authored
[Simple Mono Profiler] Add self-runtime to simple mono profiler (#16)
1 parent 4010d2c commit 235e801

File tree

1 file changed

+30
-11
lines changed

1 file changed

+30
-11
lines changed

src/SimpleProfiler/MonoProfiler/dllmain.cpp

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ struct MethodStats
1515
uint64_t call_count = 0;
1616
uint64_t total_allocation = 0;
1717
nanoseconds total_runtime = nanoseconds(0);
18+
nanoseconds self_runtime = nanoseconds(0);
1819
};
1920

2021
struct StackEntry
2122
{
2223
void* method;
2324
time_point<high_resolution_clock> entry_time;
2425
uint64_t entry_alloc;
26+
nanoseconds child_runtime;
2527
};
2628

2729
// Per-thread profiler info.
@@ -55,7 +57,17 @@ struct ThreadProfilerInfo
5557

5658
void enter_method(void* method)
5759
{
58-
stack.push_back(StackEntry{ method, high_resolution_clock::now(), mono_gc_get_used_size() });
60+
stack.push_back(StackEntry{ method, high_resolution_clock::now(), mono_gc_get_used_size(), nanoseconds(0) });
61+
}
62+
63+
MethodStats* get_method_stats(void* method)
64+
{
65+
table_t::iterator it = table.find(method);
66+
67+
if (it == table.end())
68+
it = table.insert({ method, {} }).first;
69+
70+
return &it->second;
5971
}
6072

6173
void leave_method(void* method)
@@ -71,21 +83,26 @@ struct ThreadProfilerInfo
7183
return;
7284

7385
std::lock_guard guard(stats_mut);
74-
table_t::iterator it = table.find(method);
75-
if (it == table.end())
76-
{
77-
it = table.insert({ method, {} }).first;
78-
}
7986

80-
it->second.total_runtime += now - top.entry_time;
81-
it->second.call_count++;
87+
auto stats = get_method_stats(method);
88+
89+
auto time = now - top.entry_time;
90+
stats->total_runtime += time;
91+
stats->self_runtime += time - top.child_runtime;
92+
stats->call_count++;
8293
uint64_t used_size = mono_gc_get_used_size();
8394
// If a GC has happened since the method was entered, our allocation
8495
// estimate will be messed up. Here we use a simple heuristic:
8596
// ignore any negative allocation number.
8697
if (used_size > top.entry_alloc)
8798
{
88-
it->second.total_allocation += used_size - top.entry_alloc;
99+
stats->total_allocation += used_size - top.entry_alloc;
100+
}
101+
102+
if (!stack.empty())
103+
{
104+
StackEntry& parent = stack.back();
105+
parent.child_runtime += time;
89106
}
90107
}
91108

@@ -103,6 +120,7 @@ struct ThreadProfilerInfo
103120
const char* name;
104121
uint64_t count;
105122
int64_t total_runtime;
123+
int64_t self_runtime;
106124
uint64_t total_allocation;
107125
};
108126

@@ -121,6 +139,7 @@ struct ThreadProfilerInfo
121139
.name = mono_method_full_name(entry.first),
122140
.count = entry.second.call_count,
123141
.total_runtime = entry.second.total_runtime.count(),
142+
.self_runtime = entry.second.self_runtime.count(),
124143
.total_allocation = entry.second.total_allocation });
125144
}
126145
}
@@ -136,13 +155,13 @@ struct ThreadProfilerInfo
136155
return a.total_runtime > b.total_runtime;
137156
});
138157

139-
fs << "\"Thread\",\"Call count\",\"Method name\",\"Total runtime (ns)\",\"Total allocation (bytes)\"" << std::endl;
158+
fs << "\"Thread\",\"Call count\",\"Method name\",\"Total runtime (ns)\",\"Self runtime (ns)\",\"Total allocation (bytes)\"" << std::endl;
140159

141160
//Dump into csv
142161
for (auto& it : rows)
143162
{
144163
fs << it.thread_id << "," << it.count << ",\"" << it.name << "\"," <<
145-
it.total_runtime << "," << it.total_allocation << std::endl;
164+
it.total_runtime << "," << it.self_runtime << "," << it.total_allocation << std::endl;
146165
}
147166

148167
fs.close();

0 commit comments

Comments
 (0)