| 1241 | } |
| 1242 | |
| 1243 | void Profiler::dumpFlameGraph(Writer& out, Arguments& args, bool tree) { |
| 1244 | char title[64]; |
| 1245 | if (args._title == NULL) { |
| 1246 | Engine* active_engine = activeEngine(); |
| 1247 | if (args._counter == COUNTER_SAMPLES) { |
| 1248 | strcpy(title, active_engine->title()); |
| 1249 | } else { |
| 1250 | snprintf(title, sizeof(title), "%s (%s)", active_engine->title(), active_engine->units()); |
| 1251 | } |
| 1252 | } |
| 1253 | |
| 1254 | FlameGraph flamegraph(args._title == NULL ? title : args._title, args._counter, args._minwidth, args._reverse, args._inverted); |
| 1255 | u64 printed_sample_count = 0; |
| 1256 | |
| 1257 | { |
| 1258 | FrameName fn(args, args._style & ~STYLE_ANNOTATE, _epoch, _thread_names_lock, _thread_names); |
| 1259 | |
| 1260 | std::vector<CallTraceSample*> samples; |
| 1261 | _call_trace_storage.collectSamples(samples); |
| 1262 | |
| 1263 | for (std::vector<CallTraceSample*>::const_iterator it = samples.begin(); it != samples.end(); ++it) { |
| 1264 | CallTrace* trace = (*it)->acquireTrace(); |
| 1265 | if (trace == NULL || fn.excludeTrace(trace)) continue; |
| 1266 | |
| 1267 | u64 counter = args._counter == COUNTER_SAMPLES ? (*it)->samples : (*it)->counter; |
| 1268 | if (counter == 0) continue; |
| 1269 | |
| 1270 | int num_frames = trace->num_frames; |
| 1271 | |
| 1272 | Trie* f = flamegraph.root(); |
| 1273 | if (args._reverse) { |
| 1274 | // Thread frames always come first |
| 1275 | if (_add_sched_frame) { |
| 1276 | const char* frame_name = fn.name(trace->frames[--num_frames]); |
| 1277 | f = flamegraph.addChild(f, frame_name, FRAME_NATIVE, counter); |
| 1278 | } |
| 1279 | if (_add_thread_frame) { |
| 1280 | const char* frame_name = fn.name(trace->frames[--num_frames]); |
| 1281 | f = flamegraph.addChild(f, frame_name, FRAME_NATIVE, counter); |
| 1282 | } |
| 1283 | if (_add_cpu_frame) { |
| 1284 | const char* frame_name = fn.name(trace->frames[--num_frames]); |
| 1285 | f = flamegraph.addChild(f, frame_name, FRAME_NATIVE, counter); |
| 1286 | } |
| 1287 | |
| 1288 | for (int j = 0; j < num_frames; j++) { |
| 1289 | const char* frame_name = fn.name(trace->frames[j]); |
| 1290 | FrameTypeId frame_type = fn.type(trace->frames[j]); |
| 1291 | f = flamegraph.addChild(f, frame_name, frame_type, counter); |
| 1292 | } |
| 1293 | } else { |
| 1294 | for (int j = num_frames - 1; j >= 0; j--) { |
| 1295 | const char* frame_name = fn.name(trace->frames[j]); |
| 1296 | FrameTypeId frame_type = fn.type(trace->frames[j]); |
| 1297 | f = flamegraph.addChild(f, frame_name, frame_type, counter); |
| 1298 | } |
| 1299 | } |
| 1300 | f->_total += counter; |
nothing calls this directly
no test coverage detected