Skip to content

Commit

Permalink
small compiler performance improvement
Browse files Browse the repository at this point in the history
Inference calls eval() a lot to resolve module references, and this was
inefficient since eval() assumes expressions might need to be expanded,
so everything was going back through part of the front end. Fixed by
calling the interpreter directly.

Unfortunately this does not affect the system image build time much,
only a couple of seconds. But these are worth it:

time for `make testall`

before:
real	3m56.272s
user	13m41.657s
sys	0m4.517s

after:
real	3m6.434s
user	10m52.977s
sys	0m4.223s

time for `using Gadfly`

before:
julia> tic(); using Gadfly; toc()
elapsed time: 51.968993674 seconds

after:
julia> tic(); using Gadfly; toc()
elapsed time: 48.591181748 seconds

Would be great to find more low-hanging fruit like this.
  • Loading branch information
JeffBezanson committed Aug 1, 2014
1 parent 4f81ad9 commit 8973ed1
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 5 deletions.
4 changes: 3 additions & 1 deletion base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ function _iisconst(s::Symbol)
isdefined(m,s) && (ccall(:jl_is_const, Int32, (Any, Any), m, s) != 0)
end

_ieval(x::ANY) = eval((inference_stack::CallStack).mod, x)
_ieval(x::ANY) =
ccall(:jl_interpret_toplevel_expr_in, Any, (Any, Any, Ptr{Void}, Csize_t),
(inference_stack::CallStack).mod, x, C_NULL, 0)
_iisdefined(x::ANY) = isdefined((inference_stack::CallStack).mod, x)

_iisconst(s::SymbolNode) = _iisconst(s.name)
Expand Down
4 changes: 2 additions & 2 deletions src/interpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ jl_value_t *jl_interpret_toplevel_expr_with(jl_value_t *e,
return eval(e, locals, nl);
}

jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e,
jl_value_t **locals, size_t nl)
DLLEXPORT jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e,
jl_value_t **locals, size_t nl)
{
jl_value_t *v=NULL;
jl_module_t *last_m = jl_current_module;
Expand Down
4 changes: 2 additions & 2 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -912,8 +912,8 @@ jl_value_t *jl_interpret_toplevel_thunk_with(jl_lambda_info_t *lam,
jl_value_t *jl_interpret_toplevel_expr(jl_value_t *e);
jl_value_t *jl_interpret_toplevel_expr_with(jl_value_t *e,
jl_value_t **locals, size_t nl);
jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e,
jl_value_t **locals, size_t nl);
DLLEXPORT jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e,
jl_value_t **locals, size_t nl);
int jl_is_toplevel_only_expr(jl_value_t *e);
jl_module_t *jl_base_relative_to(jl_module_t *m);
void jl_type_infer(jl_lambda_info_t *li, jl_tuple_t *argtypes,
Expand Down

3 comments on commit 8973ed1

@tkelman
Copy link
Contributor

@tkelman tkelman commented on 8973ed1 Aug 2, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vtjnash
Copy link
Member

@vtjnash vtjnash commented on 8973ed1 Aug 4, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in a handful of places in there, you could probably replace eval with a direct symbol lookup: getfield. for example, in abstract_eval_global

@JeffBezanson
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eval(module,symbol) already has a fast path that avoids the front end.

Please sign in to comment.