added: developer `--perf` flag to see what is using the most compilation time
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 8 Feb 2024 23:21:21 +0000 (17:21 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 8 Feb 2024 23:21:21 +0000 (17:21 -0600)
compiler/include/astnodes.h
compiler/src/onyx.c
shared/include/bh.h

index 6ac937210d0ab0b6ad73338f22295834aea38841..ceaec0ce9dbc99ae889a670b221d34b5b1374248 100644 (file)
@@ -1840,6 +1840,8 @@ struct CompileOptions {
     b32 generate_symbol_info_file : 1;
     b32 generate_lsp_info_file    : 1;
 
+    b32 running_perf : 1;
+
     Runtime runtime;
 
     bh_arr(const char *) included_folders;
@@ -1895,6 +1897,9 @@ struct Context {
     u64 lexer_lines_processed;
     u64 lexer_tokens_processed;
 
+    u64 microseconds_per_state[Entity_State_Count];
+    u64 microseconds_per_type[Entity_Type_Count];
+
     u32 cycle_almost_detected : 2;
     b32 cycle_detected : 1;
 
index 986ad31cd1b315c9ca05d2dec680942412502ca3..36596a6175936ce3a767fe2a2da5aaad36f415cc 100644 (file)
@@ -142,6 +142,8 @@ static CompileOptions compile_opts_parse(bh_allocator alloc, int argc, char *arg
         .generate_tag_file = 0,
         .generate_symbol_info_file = 0,
         .generate_lsp_info_file = 0,
+
+        .running_perf = 0,
     };
 
     bh_arr_new(alloc, options.files, 2);
@@ -334,6 +336,9 @@ static CompileOptions compile_opts_parse(bh_allocator alloc, int argc, char *arg
             else if (!strcmp(argv[i], "--stack-trace")) {
                 options.stack_trace_enabled = 1;
             }
+            else if (!strcmp(argv[i], "--perf")) {
+                options.running_perf = 1;
+            }
             else if (!strcmp(argv[i], "--")) {
                 options.passthrough_argument_count = argc - i - 1;
                 options.passthrough_argument_data  = &argv[i + 1];
@@ -919,8 +924,17 @@ static i32 onyx_compile() {
         // Mostly a preventative thing to ensure that even if somehow
         // errors were left disabled, they are re-enabled in this cycle.
         onyx_errors_enable();
-
         entity_heap_remove_top(&context.entities);
+
+        u64 perf_start;
+        EntityType perf_entity_type;
+        EntityState perf_entity_state;
+        if (context.options->running_perf) {
+            perf_start = bh_time_curr_micro();
+            perf_entity_type = ent->type;
+            perf_entity_state = ent->state;
+        }
+
         b32 changed = process_entity(ent);
 
         // NOTE: VERY VERY dumb cycle breaking. Basically, remember the first entity that did
@@ -968,6 +982,14 @@ static i32 onyx_compile() {
 
         if (ent->state != Entity_State_Finalized && ent->state != Entity_State_Failed)
             entity_heap_insert_existing(&context.entities, ent);
+
+        if (context.options->running_perf) {
+            u64 perf_end = bh_time_curr_micro();
+
+            u64 duration = perf_end - perf_start;
+            context.microseconds_per_type[perf_entity_type] += duration;
+            context.microseconds_per_state[perf_entity_state] += duration;
+        }
     }
 
     //
@@ -997,6 +1019,17 @@ static i32 onyx_compile() {
         onyx_docs_emit_odoc(context.options->documentation_file);
     }
 
+    if (context.options->running_perf) {
+        fori (i, 0, Entity_State_Count) {
+            printf("| %27s | %10lu us |\n", entity_state_strings[i], context.microseconds_per_state[i]);
+        }
+        printf("\n");
+        fori (i, 0, Entity_Type_Count) {
+            printf("| %27s | %10lu us |\n", entity_type_strings[i], context.microseconds_per_type[i]);
+        }
+        printf("\n");
+    }
+
     return ONYX_COMPILER_PROGRESS_SUCCESS;
 }
 
index 4a3eaa481a87ddbd66febb8d6b7da76461414ef4..5004b9c68fdd886b1addc533c5e58240fb52c96c 100644 (file)
@@ -908,6 +908,7 @@ BH_ALLOCATOR_PROC(bh_managed_heap_allocator_proc);
 // TIME / DURATION
 //------------------------------------------------------------------------------
 u64 bh_time_curr();
+u64 bh_time_curr_micro();
 u64 bh_time_duration(u64 old);
 
 
@@ -3079,6 +3080,26 @@ void bh_imap_clear(bh_imap* imap) {
 
 
 
+u64 bh_time_curr_micro() {
+#if defined(_BH_WINDOWS)
+    LARGE_INTEGER result;
+    QueryPerformanceCounter(&result);
+    return (u64) result.QuadPart; // This is wrong and not micro-seconds...
+
+#elif defined(_BH_LINUX) || defined(_BH_DARWIN)
+    struct timespec spec;
+    clock_gettime(CLOCK_REALTIME, &spec);
+
+    time_t sec = spec.tv_sec;
+    u64 ms  = spec.tv_nsec / 1000;
+    if (ms > 999999) {
+        sec++;
+        ms -= 1000000;
+    }
+
+    return sec * 1000000 + ms;
+#endif
+}
 
 u64 bh_time_curr() {
 #if defined(_BH_WINDOWS)