Skip to content

Commit

Permalink
emit precompile statements to separate file (JuliaLang#28419)
Browse files Browse the repository at this point in the history
if the filename to trace--compile is stdout, print to the stdout stream
  • Loading branch information
KristofferC committed Aug 3, 2018
1 parent 0e32871 commit cfc7475
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 70 deletions.
2 changes: 1 addition & 1 deletion base/options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ struct JLOptions
warn_overwrite::Int8
can_inline::Int8
polly::Int8
trace_compile::Int8
trace_compile::Ptr{UInt8}
fast_math::Int8
worker::Int8
cookie::Ptr{UInt8}
Expand Down
98 changes: 48 additions & 50 deletions contrib/generate_precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,65 +82,63 @@ function generate_precompile_statements()
print("Generating precompile statements...")
sysimg = isempty(ARGS) ? joinpath(dirname(Sys.BINDIR), "lib", "julia", "sys.ji") : ARGS[1]

# Run a repl process and replay our script
stdout_accumulator, stderr_accumulator = IOBuffer(), IOBuffer()
with_fake_pty() do slave, master
with_fake_pty() do slave_err, master_err
done = false
withenv("JULIA_HISTORY" => tempname(), "JULIA_PROJECT" => nothing,
"TERM" => "") do
p = run(`$(julia_cmd()) -O0 --trace-compile=yes --sysimage $sysimg
--startup-file=no --color=yes`,
slave, slave, slave_err; wait=false)
readuntil(master, "julia>", keep=true)
for (tty, accumulator) in (master => stdout_accumulator,
master_err => stderr_accumulator)
@async begin
while true
done && break
write(accumulator, readavailable(tty))
mktemp() do precompile_file, _
# Run a repl process and replay our script
stdout_accumulator, stderr_accumulator = IOBuffer(), IOBuffer()
with_fake_pty() do slave, master
with_fake_pty() do slave_err, master_err
done = false
withenv("JULIA_HISTORY" => tempname(), "JULIA_PROJECT" => nothing,
"TERM" => "") do
p = run(`$(julia_cmd()) -O0 --trace-compile=$precompile_file --sysimage $sysimg
--startup-file=no --color=yes`,
slave, slave, slave_err; wait=false)
readuntil(master, "julia>", keep=true)
for (tty, accumulator) in (master => stdout_accumulator,
master_err => stderr_accumulator)
@async begin
while true
done && break
write(accumulator, readavailable(tty))
end
end
end
end
if have_repl
for l in split(precompile_script, '\n'; keepempty=false)
write(master, l, '\n')
if have_repl
for l in split(precompile_script, '\n'; keepempty=false)
write(master, l, '\n')
end
end
write(master, "exit()\n")
wait(p)
done = true
end
write(master, "exit()\n")
wait(p)
done = true
end
end
end

stderr_output = String(take!(stderr_accumulator))
# println(stderr_output)
# stdout_output = String(take!(stdout_accumulator))
# println(stdout_output)

# Extract the precompile statements from stderr
statements = Set{String}()
for statement in split(stderr_output, '\n')
m = match(r"(precompile\(Tuple{.*)", statement)
m === nothing && continue
statement = m.captures[1]
occursin(r"Main.", statement) && continue
push!(statements, statement)
end
# Check what the REPL displayed
# stdout_output = String(take!(stdout_accumulator))
# println(stdout_output)

# Load the precompile statements
statements_ordered = join(sort(collect(statements)), '\n')
# println(statements_ordered)
if have_repl
# Seems like a reasonable number right now, adjust as needed
@assert length(statements) > 700
end
# Extract the precompile statements from stderr
statements = Set{String}()
for statement in split(read(precompile_file, String), '\n')
occursin("Main.", statement) && continue
push!(statements, statement)
end

# Load the precompile statements
statements_ordered = join(sort(collect(statements)), '\n')
# println(statements_ordered)
if have_repl
# Seems like a reasonable number right now, adjust as needed
@assert length(statements) > 700
end

Base.include_string(PrecompileStagingArea, statements_ordered)
print(" $(length(statements)) generated in ")
Base.time_print((time() - start_time) * 10^9)
println()
Base.include_string(PrecompileStagingArea, statements_ordered)
print(" $(length(statements)) generated in ")
Base.time_print((time() - start_time) * 10^9)
println()
end
end

# Fall back to explicit list on Windows, might as well include them
Expand Down
2 changes: 1 addition & 1 deletion contrib/precompile_explicit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Steps to regenerate this file:
# 1. Remove all `precompile` calls
# 2. Rebuild system image
# 3. Start julia with `--trace-compile=yes and do some stuff
# 3. Start julia with `--trace-compile=precompiles.txt and do some stuff
# 5. Run `grep -v '#[0-9]' precompiles.txt >> contrib/precompile_explicit.jl`
# (filters out closures, which might have different generated names in different environments)
# This list is only used on Windows, otherwise precompile statements are generated dynamically.
Expand Down
25 changes: 21 additions & 4 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,10 @@ static jl_method_instance_t *cache_method(

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)
{
// TODO: Merge with jl_dump_compiles?
static ios_t f_precompile;
static JL_STREAM* s_precompile = NULL;

// caller must hold the mt->writelock
jl_typemap_entry_t *entry = NULL;
entry = jl_typemap_assoc_by_type(mt->cache, (jl_value_t*)tt, NULL, /*subtype*/1, jl_cachearg_offset(mt), world, /*max_world_mask*/0);
Expand All @@ -1088,11 +1092,24 @@ static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype
if (entry != NULL) {
jl_method_t *m = entry->func.method;
if (!jl_has_call_ambiguities((jl_value_t*)tt, m)) {
if (jl_options.trace_compile) {
if (jl_options.trace_compile != NULL) {
if (s_precompile == NULL) {
const char* t = jl_options.trace_compile;
if (!strncmp(t, "stderr", 6))
s_precompile = JL_STDERR;
else {
if (ios_file(&f_precompile, t, 1, 1, 1, 1) == NULL)
jl_errorf("cannot open precompile statement file \"%s\" for writing", t);
s_precompile = (JL_STREAM*) &f_precompile;
}
}
if (!jl_has_free_typevars((jl_value_t*)tt)) {
jl_printf(JL_STDERR, "precompile(");
jl_static_show(JL_STDERR, (jl_value_t*)tt);
jl_printf(JL_STDERR, ")\n");
jl_printf(s_precompile, "precompile(");
jl_static_show(s_precompile, (jl_value_t*)tt);
jl_printf(s_precompile, ")\n");

if (s_precompile != JL_STDERR)
ios_flush(&f_precompile);
}
}
if (!mt_cache) {
Expand Down
16 changes: 4 additions & 12 deletions src/jloptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,7 @@ jl_options_t jl_options = { 0, // quiet
0, // method overwrite warning
1, // can_inline
JL_OPTIONS_POLLY_ON, // polly
#ifdef TRACE_COMPILE
1, // trace_compile
#else
0, // trace_compile
#endif
NULL, // trace_compile
JL_OPTIONS_FAST_MATH_DEFAULT,
0, // worker
NULL, // cookie
Expand Down Expand Up @@ -575,13 +571,9 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp)
}
break;
case opt_trace_compile:
if (!strcmp(optarg,"yes"))
jl_options.trace_compile = 1;
else if (!strcmp(optarg,"no"))
jl_options.trace_compile = 0;
else {
jl_errorf("julia: invalid argument to --trace-compile (%s)", optarg);
}
jl_options.trace_compile = strdup(optarg);
if (!jl_options.trace_compile)
jl_errorf("fatal error: failed to allocate memory: %s", strerror(errno));
break;
case opt_math_mode:
if (!strcmp(optarg,"ieee"))
Expand Down
2 changes: 1 addition & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -1799,7 +1799,7 @@ typedef struct {
int8_t warn_overwrite;
int8_t can_inline;
int8_t polly;
int8_t trace_compile;
const char *trace_compile;
int8_t fast_math;
int8_t worker;
const char *cookie;
Expand Down
1 change: 0 additions & 1 deletion src/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@

// print all signatures type inference is invoked on
//#define TRACE_INFERENCE
//#define TRACE_COMPILE

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

0 comments on commit cfc7475

Please sign in to comment.