Skip to content

Commit cfc7475

Browse files
authored
emit precompile statements to separate file (#28419)
if the filename to trace--compile is stdout, print to the stdout stream
1 parent 0e32871 commit cfc7475

File tree

7 files changed

+76
-70
lines changed

7 files changed

+76
-70
lines changed

base/options.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct JLOptions
2626
warn_overwrite::Int8
2727
can_inline::Int8
2828
polly::Int8
29-
trace_compile::Int8
29+
trace_compile::Ptr{UInt8}
3030
fast_math::Int8
3131
worker::Int8
3232
cookie::Ptr{UInt8}

contrib/generate_precompile.jl

Lines changed: 48 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -82,65 +82,63 @@ function generate_precompile_statements()
8282
print("Generating precompile statements...")
8383
sysimg = isempty(ARGS) ? joinpath(dirname(Sys.BINDIR), "lib", "julia", "sys.ji") : ARGS[1]
8484

85-
# Run a repl process and replay our script
86-
stdout_accumulator, stderr_accumulator = IOBuffer(), IOBuffer()
87-
with_fake_pty() do slave, master
88-
with_fake_pty() do slave_err, master_err
89-
done = false
90-
withenv("JULIA_HISTORY" => tempname(), "JULIA_PROJECT" => nothing,
91-
"TERM" => "") do
92-
p = run(`$(julia_cmd()) -O0 --trace-compile=yes --sysimage $sysimg
93-
--startup-file=no --color=yes`,
94-
slave, slave, slave_err; wait=false)
95-
readuntil(master, "julia>", keep=true)
96-
for (tty, accumulator) in (master => stdout_accumulator,
97-
master_err => stderr_accumulator)
98-
@async begin
99-
while true
100-
done && break
101-
write(accumulator, readavailable(tty))
85+
mktemp() do precompile_file, _
86+
# Run a repl process and replay our script
87+
stdout_accumulator, stderr_accumulator = IOBuffer(), IOBuffer()
88+
with_fake_pty() do slave, master
89+
with_fake_pty() do slave_err, master_err
90+
done = false
91+
withenv("JULIA_HISTORY" => tempname(), "JULIA_PROJECT" => nothing,
92+
"TERM" => "") do
93+
p = run(`$(julia_cmd()) -O0 --trace-compile=$precompile_file --sysimage $sysimg
94+
--startup-file=no --color=yes`,
95+
slave, slave, slave_err; wait=false)
96+
readuntil(master, "julia>", keep=true)
97+
for (tty, accumulator) in (master => stdout_accumulator,
98+
master_err => stderr_accumulator)
99+
@async begin
100+
while true
101+
done && break
102+
write(accumulator, readavailable(tty))
103+
end
102104
end
103105
end
104-
end
105-
if have_repl
106-
for l in split(precompile_script, '\n'; keepempty=false)
107-
write(master, l, '\n')
106+
if have_repl
107+
for l in split(precompile_script, '\n'; keepempty=false)
108+
write(master, l, '\n')
109+
end
108110
end
111+
write(master, "exit()\n")
112+
wait(p)
113+
done = true
109114
end
110-
write(master, "exit()\n")
111-
wait(p)
112-
done = true
113115
end
114116
end
115-
end
116117

117-
stderr_output = String(take!(stderr_accumulator))
118-
# println(stderr_output)
119-
# stdout_output = String(take!(stdout_accumulator))
120-
# println(stdout_output)
121-
122-
# Extract the precompile statements from stderr
123-
statements = Set{String}()
124-
for statement in split(stderr_output, '\n')
125-
m = match(r"(precompile\(Tuple{.*)", statement)
126-
m === nothing && continue
127-
statement = m.captures[1]
128-
occursin(r"Main.", statement) && continue
129-
push!(statements, statement)
130-
end
118+
# Check what the REPL displayed
119+
# stdout_output = String(take!(stdout_accumulator))
120+
# println(stdout_output)
131121

132-
# Load the precompile statements
133-
statements_ordered = join(sort(collect(statements)), '\n')
134-
# println(statements_ordered)
135-
if have_repl
136-
# Seems like a reasonable number right now, adjust as needed
137-
@assert length(statements) > 700
138-
end
122+
# Extract the precompile statements from stderr
123+
statements = Set{String}()
124+
for statement in split(read(precompile_file, String), '\n')
125+
occursin("Main.", statement) && continue
126+
push!(statements, statement)
127+
end
128+
129+
# Load the precompile statements
130+
statements_ordered = join(sort(collect(statements)), '\n')
131+
# println(statements_ordered)
132+
if have_repl
133+
# Seems like a reasonable number right now, adjust as needed
134+
@assert length(statements) > 700
135+
end
139136

140-
Base.include_string(PrecompileStagingArea, statements_ordered)
141-
print(" $(length(statements)) generated in ")
142-
Base.time_print((time() - start_time) * 10^9)
143-
println()
137+
Base.include_string(PrecompileStagingArea, statements_ordered)
138+
print(" $(length(statements)) generated in ")
139+
Base.time_print((time() - start_time) * 10^9)
140+
println()
141+
end
144142
end
145143

146144
# Fall back to explicit list on Windows, might as well include them

contrib/precompile_explicit.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Steps to regenerate this file:
44
# 1. Remove all `precompile` calls
55
# 2. Rebuild system image
6-
# 3. Start julia with `--trace-compile=yes and do some stuff
6+
# 3. Start julia with `--trace-compile=precompiles.txt and do some stuff
77
# 5. Run `grep -v '#[0-9]' precompiles.txt >> contrib/precompile_explicit.jl`
88
# (filters out closures, which might have different generated names in different environments)
99
# This list is only used on Windows, otherwise precompile statements are generated dynamically.

src/gf.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,10 @@ static jl_method_instance_t *cache_method(
10711071

10721072
static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *tt, int mt_cache, int allow_exec, size_t world)
10731073
{
1074+
// TODO: Merge with jl_dump_compiles?
1075+
static ios_t f_precompile;
1076+
static JL_STREAM* s_precompile = NULL;
1077+
10741078
// caller must hold the mt->writelock
10751079
jl_typemap_entry_t *entry = NULL;
10761080
entry = jl_typemap_assoc_by_type(mt->cache, (jl_value_t*)tt, NULL, /*subtype*/1, jl_cachearg_offset(mt), world, /*max_world_mask*/0);
@@ -1088,11 +1092,24 @@ static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype
10881092
if (entry != NULL) {
10891093
jl_method_t *m = entry->func.method;
10901094
if (!jl_has_call_ambiguities((jl_value_t*)tt, m)) {
1091-
if (jl_options.trace_compile) {
1095+
if (jl_options.trace_compile != NULL) {
1096+
if (s_precompile == NULL) {
1097+
const char* t = jl_options.trace_compile;
1098+
if (!strncmp(t, "stderr", 6))
1099+
s_precompile = JL_STDERR;
1100+
else {
1101+
if (ios_file(&f_precompile, t, 1, 1, 1, 1) == NULL)
1102+
jl_errorf("cannot open precompile statement file \"%s\" for writing", t);
1103+
s_precompile = (JL_STREAM*) &f_precompile;
1104+
}
1105+
}
10921106
if (!jl_has_free_typevars((jl_value_t*)tt)) {
1093-
jl_printf(JL_STDERR, "precompile(");
1094-
jl_static_show(JL_STDERR, (jl_value_t*)tt);
1095-
jl_printf(JL_STDERR, ")\n");
1107+
jl_printf(s_precompile, "precompile(");
1108+
jl_static_show(s_precompile, (jl_value_t*)tt);
1109+
jl_printf(s_precompile, ")\n");
1110+
1111+
if (s_precompile != JL_STDERR)
1112+
ios_flush(&f_precompile);
10961113
}
10971114
}
10981115
if (!mt_cache) {

src/jloptions.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,7 @@ jl_options_t jl_options = { 0, // quiet
5555
0, // method overwrite warning
5656
1, // can_inline
5757
JL_OPTIONS_POLLY_ON, // polly
58-
#ifdef TRACE_COMPILE
59-
1, // trace_compile
60-
#else
61-
0, // trace_compile
62-
#endif
58+
NULL, // trace_compile
6359
JL_OPTIONS_FAST_MATH_DEFAULT,
6460
0, // worker
6561
NULL, // cookie
@@ -575,13 +571,9 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp)
575571
}
576572
break;
577573
case opt_trace_compile:
578-
if (!strcmp(optarg,"yes"))
579-
jl_options.trace_compile = 1;
580-
else if (!strcmp(optarg,"no"))
581-
jl_options.trace_compile = 0;
582-
else {
583-
jl_errorf("julia: invalid argument to --trace-compile (%s)", optarg);
584-
}
574+
jl_options.trace_compile = strdup(optarg);
575+
if (!jl_options.trace_compile)
576+
jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno));
585577
break;
586578
case opt_math_mode:
587579
if (!strcmp(optarg,"ieee"))

src/julia.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1799,7 +1799,7 @@ typedef struct {
17991799
int8_t warn_overwrite;
18001800
int8_t can_inline;
18011801
int8_t polly;
1802-
int8_t trace_compile;
1802+
const char *trace_compile;
18031803
int8_t fast_math;
18041804
int8_t worker;
18051805
const char *cookie;

src/options.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@
8989

9090
// print all signatures type inference is invoked on
9191
//#define TRACE_INFERENCE
92-
//#define TRACE_COMPILE
9392

9493
// print all generic method dispatches (excludes inlined and specialized call
9594
// sites). this generally prints too much output to be useful.

0 commit comments

Comments
 (0)