Created
April 18, 2017 17:07
-
-
Save timo/1dab05a80811102a9437894adff39e87 to your computer and use it in GitHub Desktop.
don't recurse through the profiler's call graph
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/profiler/instrument.c b/src/profiler/instrument.c | |
index 399fd41..ad1c1c3 100644 | |
--- a/src/profiler/instrument.c | |
+++ b/src/profiler/instrument.c | |
@@ -1,5 +1,44 @@ | |
#include "moar.h" | |
+typedef struct { | |
+ MVMuint32 items; | |
+ MVMuint32 start; | |
+ MVMuint32 alloc; | |
+ | |
+ MVMProfileCallNode **list; | |
+} NodeWorklist; | |
+ | |
+static void add_node(MVMThreadContext *tc, NodeWorklist *list, MVMProfileCallNode *node) { | |
+ if (list->start + list->items < list->alloc) { | |
+ /* Add at the end */ | |
+ list->items++; | |
+ list->list[list->start + list->items] = node; | |
+ } else if (list->start > 0) { | |
+ /* End reached, add to the start now */ | |
+ list->start--; | |
+ list->list[list->start] = node; | |
+ } else { | |
+ /* Filled up the whole list. Make it bigger */ | |
+ list->alloc *= 2; | |
+ list->list = MVM_realloc(list->list, list->alloc * sizeof(MVMProfileCallNode *)); | |
+ } | |
+} | |
+ | |
+static MVMProfileCallNode *take_node(MVMThreadContext *tc, NodeWorklist *list) { | |
+ MVMProfileCallNode *result = NULL; | |
+ if (list->items == 0) { | |
+ MVM_panic(1, "profiler: tried to take a node from an empty node worklist"); | |
+ } | |
+ if (list->start > 0) { | |
+ result = list->list[list->start]; | |
+ list->start++; | |
+ } else { | |
+ result = list->list[list->start + list->items]; | |
+ list->items--; | |
+ } | |
+ return result; | |
+} | |
+ | |
/* Adds an instruction to log an allocation. */ | |
static void add_allocation_logging(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshBB *bb, MVMSpeshIns *ins) { | |
MVMSpeshIns *alloc_ins = MVM_spesh_alloc(tc, g, sizeof(MVMSpeshIns)); | |
@@ -370,11 +409,14 @@ static MVMObject * dump_call_graph_node(MVMThreadContext *tc, ProfDumpStrs *pds, | |
if (pcn->num_succ) { | |
MVMObject *callees = new_array(tc); | |
MVMuint64 exclusive_time = pcn->total_time; | |
+ unsigned int interval_id = startInterval(tc, "dumping call graph node successors"); | |
+ annotateInterval(pcn->num_succ, interval_id, "this many successors"); | |
for (i = 0; i < pcn->num_succ; i++) { | |
MVM_repr_push_o(tc, callees, | |
dump_call_graph_node(tc, pds, pcn->succ[i])); | |
exclusive_time -= pcn->succ[i]->total_time; | |
} | |
+ stopInterval(interval_id, "dumped call graph node successors"); | |
MVM_repr_bind_key_o(tc, node_hash, pds->exclusive_time, | |
box_i(tc, exclusive_time / 1000)); | |
MVM_repr_bind_key_o(tc, node_hash, pds->callees, callees); | |
@@ -529,15 +571,29 @@ MVMObject * MVM_profile_instrumented_end(MVMThreadContext *tc) { | |
/* Marks objects held in the profiling graph. */ | |
-static void mark_call_graph_node(MVMThreadContext *tc, MVMProfileCallNode *node, MVMGCWorklist *worklist) { | |
+static void mark_call_graph_node(MVMThreadContext *tc, MVMProfileCallNode *node, NodeWorklist *nodelist, MVMGCWorklist *worklist) { | |
MVMuint32 i; | |
MVM_gc_worklist_add(tc, worklist, &(node->sf)); | |
for (i = 0; i < node->num_alloc; i++) | |
MVM_gc_worklist_add(tc, worklist, &(node->alloc[i].type)); | |
for (i = 0; i < node->num_succ; i++) | |
- mark_call_graph_node(tc, node->succ[i], worklist); | |
+ add_node(tc, nodelist, node->succ[i]); | |
} | |
void MVM_profile_instrumented_mark_data(MVMThreadContext *tc, MVMGCWorklist *worklist) { | |
- if (tc->prof_data) | |
- mark_call_graph_node(tc, tc->prof_data->call_graph, worklist); | |
+ if (tc->prof_data) { | |
+ /* Allocate our worklist on the stack. */ | |
+ NodeWorklist nodelist; | |
+ nodelist.items = 0; | |
+ nodelist.start = 0; | |
+ nodelist.alloc = 256; | |
+ nodelist.list = MVM_malloc(nodelist.alloc * sizeof(MVMProfileCallNode *)); | |
+ | |
+ add_node(tc, &nodelist, tc->prof_data->call_graph); | |
+ | |
+ while (nodelist.items) { | |
+ mark_call_graph_node(tc, take_node(tc, &nodelist), &nodelist, worklist); | |
+ } | |
+ | |
+ MVM_free(nodelist.list); | |
+ } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment