Skip to content

Commit f843f0a

Browse files
whatsthecraickpamnany
authored andcommitted
Record codegen lock waiting time
- Add control for recording wait time to Julia mutexes - Enable this control for the codegen lock - Record the codegen lock waiting time in `jl_generate_fptr` when called from `jl_compile_method_internal` - Emit the codegen lock waiting time as well as the codegen lock nesting level in compilation traces
1 parent 061a139 commit f843f0a

File tree

6 files changed

+34
-5
lines changed

6 files changed

+34
-5
lines changed

src/gf.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2381,7 +2381,7 @@ JL_DLLEXPORT void jl_force_trace_compile_timing_disable(void)
23812381
jl_atomic_fetch_add(&jl_force_trace_compile_timing_enabled, -1);
23822382
}
23832383

2384-
static void record_precompile_statement(jl_method_instance_t *mi, double compilation_time)
2384+
static void record_precompile_statement(jl_method_instance_t *mi, double compilation_time, double codegen_lock_waiting_time)
23852385
{
23862386
static ios_t f_precompile;
23872387
static JL_STREAM* s_precompile = NULL;
@@ -2392,6 +2392,12 @@ static void record_precompile_statement(jl_method_instance_t *mi, double compila
23922392
if (!jl_is_method(def))
23932393
return;
23942394

2395+
// nested layer of this precompile statement
2396+
int nested_level = 0;
2397+
if (jl_atomic_load_relaxed(&(jl_codegen_lock.owner)) == jl_current_task) {
2398+
nested_level = jl_codegen_lock.count;
2399+
}
2400+
23952401
JL_LOCK(&precomp_statement_out_lock);
23962402
if (s_precompile == NULL) {
23972403
const char *t = jl_options.trace_compile;
@@ -2409,7 +2415,20 @@ static void record_precompile_statement(jl_method_instance_t *mi, double compila
24092415
jl_printf(s_precompile, "#= %6.1f =# ", compilation_time / 1e6);
24102416
jl_printf(s_precompile, "precompile(");
24112417
jl_static_show(s_precompile, mi->specTypes);
2412-
jl_printf(s_precompile, ")\n");
2418+
jl_printf(s_precompile, ")");
2419+
2420+
// compilation inline properties/files as a json dictionary
2421+
if (force_trace_compile || jl_options.trace_compile_timing) {
2422+
jl_printf(s_precompile, " #= { "); // json starts
2423+
// nested level: 0 -> not nested, >= 1, nested amount
2424+
jl_printf(s_precompile, "\"nested_levels\": %d, ", nested_level);
2425+
// time spent waiting to acquire the codegen lock, in milliseconds
2426+
jl_printf(s_precompile, "\"codegen_waiting_time\": %.2f ", codegen_lock_waiting_time / 1e6);
2427+
2428+
jl_printf(s_precompile, "} =#"); // json ends
2429+
}
2430+
jl_printf(s_precompile, "\n");
2431+
24132432
if (s_precompile != JL_STDERR)
24142433
ios_flush(&f_precompile);
24152434
}
@@ -2569,7 +2588,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t
25692588
codeinst->rettype_const = unspec->rettype_const;
25702589
jl_atomic_store_release(&codeinst->invoke, unspec_invoke);
25712590
jl_mi_cache_insert(mi, codeinst);
2572-
record_precompile_statement(mi, 0);
2591+
record_precompile_statement(mi, 0, 0);
25732592
return codeinst;
25742593
}
25752594
}
@@ -2586,7 +2605,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t
25862605
0, 1, ~(size_t)0, 0, 0, jl_nothing, 0);
25872606
jl_atomic_store_release(&codeinst->invoke, jl_fptr_interpret_call);
25882607
jl_mi_cache_insert(mi, codeinst);
2589-
record_precompile_statement(mi, 0);
2608+
record_precompile_statement(mi, 0, 0);
25902609
return codeinst;
25912610
}
25922611
if (compile_option == JL_OPTIONS_COMPILE_OFF) {
@@ -2598,7 +2617,9 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t
25982617

25992618
double compile_time = jl_hrtime();
26002619
int did_compile = 0;
2620+
uint64_t codegen_lock_wt_before = jl_current_task->lock_waiting_time;
26012621
codeinst = jl_generate_fptr(mi, world, &did_compile);
2622+
uint64_t codegen_lock_waiting_time = jl_current_task->lock_waiting_time - codegen_lock_wt_before;
26022623
compile_time = jl_hrtime() - compile_time;
26032624

26042625
if (!codeinst) {
@@ -2641,7 +2662,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t
26412662
jl_mi_cache_insert(mi, codeinst);
26422663
}
26432664
else if (did_compile) {
2644-
record_precompile_statement(mi, compile_time);
2665+
record_precompile_statement(mi, compile_time, (double)codegen_lock_waiting_time);
26452666
}
26462667
jl_atomic_store_relaxed(&codeinst->precompile, 1);
26472668
return codeinst;

src/init.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ static void init_global_mutexes(void) {
735735
JL_MUTEX_INIT(&newly_inferred_mutex, "newly_inferred_mutex");
736736
JL_MUTEX_INIT(&global_roots_lock, "global_roots_lock");
737737
JL_MUTEX_INIT(&jl_codegen_lock, "jl_codegen_lock");
738+
jl_codegen_lock.record_waiting_time = 1; // 0 = no, 1 = yes
738739
JL_MUTEX_INIT(&typecache_lock, "typecache_lock");
739740
}
740741

src/julia.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,6 +2085,7 @@ typedef struct _jl_task_t {
20852085
size_t bufsz; // actual sizeof stkbuf
20862086
unsigned int copy_stack:31; // sizeof stack for copybuf
20872087
unsigned int started:1;
2088+
uint64_t lock_waiting_time;
20882089
} jl_task_t;
20892090

20902091
#define JL_TASK_STATE_RUNNABLE 0

src/julia_threads.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ struct _jl_task_t;
120120
typedef struct {
121121
_Atomic(struct _jl_task_t*) owner;
122122
uint32_t count;
123+
int32_t record_waiting_time; // 0 => no (default), 1 => yes
123124
} jl_mutex_t;
124125

125126
struct _jl_bt_element_t;

src/task.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,7 @@ JL_DLLEXPORT jl_task_t *jl_new_task(jl_function_t *start, jl_value_t *completion
11171117
#ifdef _COMPILER_ASAN_ENABLED_
11181118
t->ctx.asan_fake_stack = NULL;
11191119
#endif
1120+
t->lock_waiting_time = 0;
11201121
return t;
11211122
}
11221123

src/threading.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,7 @@ void _jl_mutex_init(jl_mutex_t *lock, const char *name) JL_NOTSAFEPOINT
800800
{
801801
jl_atomic_store_relaxed(&lock->owner, (jl_task_t*)NULL);
802802
lock->count = 0;
803+
lock->record_waiting_time = 0;
803804
jl_profile_lock_init(lock, name);
804805
}
805806

@@ -818,10 +819,13 @@ void _jl_mutex_wait(jl_task_t *self, jl_mutex_t *lock, int safepoint)
818819
return;
819820
}
820821
JL_TIMING(LOCK_SPIN, LOCK_SPIN);
822+
uint64_t t0 = lock->record_waiting_time ? jl_hrtime() : 0;
821823
while (1) {
822824
if (owner == NULL && jl_atomic_cmpswap(&lock->owner, &owner, self)) {
823825
lock->count = 1;
824826
jl_profile_lock_acquired(lock);
827+
if (lock->record_waiting_time)
828+
self->lock_waiting_time += jl_hrtime() - t0;
825829
return;
826830
}
827831
if (safepoint) {

0 commit comments

Comments
 (0)