diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 75f2b244dacd3..2ca97289f62d9 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -251,7 +251,7 @@ static jl_callptr_t _jl_compile_codeinst( size_t i = 0; for (auto &def : emitted) { jl_code_instance_t *this_code = def.first; - if (i < 10) + if (i < jl_timing_print_limit) jl_timing_show_func_sig(this_code->def->specTypes, JL_TIMING_CURRENT_BLOCK); jl_llvm_functions_t decls = std::get<1>(def.second); @@ -297,7 +297,7 @@ static jl_callptr_t _jl_compile_codeinst( fptr = addr; i++; } - if (i > 10) + if (i > jl_timing_print_limit) jl_timing_printf(JL_TIMING_CURRENT_BLOCK, "... <%d methods truncated>", i - 10); uint64_t end_time = 0; diff --git a/src/jlapi.c b/src/jlapi.c index 8f5e3e6cb13dc..369f4d6ec3ff1 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -685,8 +685,11 @@ static void rr_detach_teleport(void) { JL_DLLEXPORT int jl_repl_entrypoint(int argc, char *argv[]) { #ifdef USE_TRACY - if (getenv("WAIT_FOR_TRACY")) - while (!TracyCIsConnected) ; // Wait for connection + // Apply e.g. JULIA_TIMING_SUBSYSTEMS="+GC,-INFERENCE" and + // JULIA_TIMING_METADATA_PRINT_LIMIT=20 + jl_timing_apply_env(); + if (getenv("JULIA_WAIT_FOR_TRACY")) + while (!TracyCIsConnected) jl_cpu_pause(); // Wait for connection #endif // no-op on Windows, note that the caller must have already converted diff --git a/src/task.c b/src/task.c index e73b19563e336..123cfaac00163 100644 --- a/src/task.c +++ b/src/task.c @@ -1222,8 +1222,6 @@ CFI_NORETURN _start_task(); } -const char* fiber = "task"; - STATIC_OR_JS void NOINLINE JL_NORETURN _start_task(void) { CFI_NORETURN diff --git a/src/timing.c b/src/timing.c index c3ba3809884bf..7337902010a3d 100644 --- a/src/timing.c +++ b/src/timing.c @@ -36,6 +36,11 @@ JL_DLLEXPORT uint64_t jl_timing_enable_mask = 0xFFFFFFFFFFFFFFFF; #endif JL_DLLEXPORT uint64_t jl_timing_counts[(int)JL_TIMING_LAST] = {0}; + +// Used to as an item limit when several strings of metadata can +// potentially be associated with a single timing zone. +JL_DLLEXPORT uint32_t jl_timing_print_limit = 10; + const char *jl_timing_names[(int)JL_TIMING_LAST] = { #define X(name) #name @@ -100,14 +105,16 @@ void jl_timing_block_enter_task(jl_task_t *ct, jl_ptls_t ptls, jl_timing_block_t jl_timing_block_t *jl_timing_block_exit_task(jl_task_t *ct, jl_ptls_t ptls) { #ifdef USE_TRACY - // Tracy is fairly strict about not leaving a fiber that - // hasn't been entered, which happens often when - // connecting to a running Julia session. + // Tracy is fairly strict about not leaving a fiber that hasn't + // been entered, which happens often when connecting to a running + // Julia session. + // + // Eventually, Tracy will support telling the server which fibers + // are active upon connection, but until then we work around the + // problem by not explicitly leaving the fiber at all. // - // Eventually, Tracy will support telling the server that - // which fibers are active upon connection, but until then - // work around around the problem by just entering the new - // fiber directly, which implicitly leaves any active fibers. + // Later when we enter the new fiber directly, that will cause the + // the active fiber to be left implicitly. //TracyCFiberLeave; #endif @@ -220,11 +227,71 @@ JL_DLLEXPORT int jl_timing_set_enable(const char *subsystem, uint8_t enabled) return -1; } +static void jl_timing_set_enable_from_env(void) +{ + const char *env = getenv("JULIA_TIMING_SUBSYSTEMS"); + if (!env) + return; + + // Copy `env`, so that we can modify it + size_t sz = strlen(env) + 1; + char *env_copy = (char *)malloc(sz); + memcpy(env_copy, env, sz); + + char *subsystem = env_copy; + char *ch = subsystem; + uint8_t enable = 1; + while (1) { + // +SUBSYSTEM means enable, -SUBSYSTEM means disable + if (*subsystem == '+' || *subsystem == '-') + enable = (*subsystem++ == '+'); + + if (*ch == ',') { + *ch++ = '\0'; + if ((*subsystem != '\0') && jl_timing_set_enable(subsystem, enable)) + fprintf(stderr, "warning: unable to configure timing for non-existent subsystem \"%s\"\n", subsystem); + + subsystem = ch; + enable = 1; + } + else if (*ch == '\0') { + if ((*subsystem != '\0') && jl_timing_set_enable(subsystem, enable)) + fprintf(stderr, "warning: unable to configure timing for non-existent subsystem \"%s\"\n", subsystem); + + break; + } + else ch++; + } + free(env_copy); +} + +static void jl_timing_set_print_limit_from_env(void) +{ + const char *const env = getenv("JULIA_TIMING_METADATA_PRINT_LIMIT"); + if (!env) + return; + + char *endp; + long value = strtol(env, &endp, 10); + if (*endp == '\0' && value >= 0 && value <= UINT32_MAX) + jl_timing_print_limit = (uint32_t)value; +} + +void jl_timing_apply_env(void) +{ + // JULIA_TIMING_SUBSYSTEMS + jl_timing_set_enable_from_env(); + + // JULIA_TIMING_METADATA_PRINT_LIMIT + jl_timing_set_print_limit_from_env(); +} + #else void jl_init_timing(void) { } void jl_destroy_timing(void) { } JL_DLLEXPORT int jl_timing_set_enable(const char *subsystem, uint8_t enabled) { return -1; } +JL_DLLEXPORT uint32_t jl_timing_print_limit = 0; #endif diff --git a/src/timing.h b/src/timing.h index d7dc53ad0e8be..d6e4c6d80ab63 100644 --- a/src/timing.h +++ b/src/timing.h @@ -16,6 +16,21 @@ void jl_destroy_timing(void) JL_NOTSAFEPOINT; // Returns -1 if no matching sub-system was found. int jl_timing_set_enable(const char *subsystem, uint8_t enabled); +// Check for environment vars "JULIA_TIMING_METADATA_PRINT_LIMIT" and +// "JULIA_TIMING_SUBSYSTEMS" and if present apply these to the metadata +// print limit and the timings enable mask, respectively. +// +// For example, to enable INFERENCE and METHOD_MATCH and disable GC: +// JULIA_TIMING_SUBSYSTEMS="+INFERENCE,-GC,+METHOD_MATCH" +// +// For example, to increase the metadata item print limit from 10 to 20: +// JULIA_TIMING_METADATA_PRINT_LIMIT=20 +void jl_timing_apply_env(void); + +// Configurable item limit, runtime code should use this to limit printing +// when adding potentially many items of metadata to a single timing zone. +extern uint32_t jl_timing_print_limit; + #ifdef __cplusplus } #endif