@time every evaluation in repl

Is it possible to hook the repl to @time every eval?

Maybe you could do something with the ast_transforms variable connected to the REPLBackend, similar to how softscope is used as default?
It seems like the default is just to insert the expression softscopt(true) at the start of the ast that is going to be evaluated so if it is possible to modify the call that creates the REPLBacken, you could then potentially create your own function to put into ast_transforms which does @time.
Though I’m not sure if you can insert a macro in the ast or if you would need to expand it yourself, but then you could probably just look at the code for @time and do something similar to what they do there.

No clue about how this really works though, just got curious and had a look at the code and made some guesses.

https://github.com/JuliaLang/julia/blob/2c2e7246373535997f9ea73186703b1f6b203e3e/stdlib/REPL/src/REPL.jl#L135-L152

The most minimal way to do this is probably

julia> push!(Base.active_repl_backend.ast_transforms, ast -> :(t = time(); r = $(ast); Base.eval(Main, :(last_time = $(time() - t))); r))
2-element Vector{Any}:
 softscope (generic function with 1 method)
 #7 (generic function with 1 method)

julia> sleep(2)

julia> last_time
2.0292770862579346
3 Likes

@pfitzseb, would it be possible to add such useful functionality to the startup.jl?

Tried adding it as is, but REPL still not available and Julia throws UndefVarError: active_repl_backend not defined.

I’m pretty sure it is possible, since for example OhMyREPL can be added in the startup file and modify the REPL looks and behaviour.

With that said I have not looked into how one would go about it, just suggesting that can be a place to start looking :slight_smile:

You can use something like

using REPL
atreplinit() do repl
    @async begin
        for i in 1:10
            if isdefined(Base, :active_repl_backend)
                push!(Base.active_repl_backend.ast_transforms, ast -> :(t = time(); r = $(ast); Base.eval(Main, :(last_time = $(time() - t))); r))
                return
            end
            sleep(0.5)
        end
        @warn "failed to install timer hook"
    end
end
1 Like

@pfitzseb, brilliant, it works.

During the tests of your script found an unrelated issue that has to do with VS Code (feel free to split this to a new topic):

On Win10 Julia 1.6.4’s REPL (all good):

julia> exp(rand(1000,1000))
julia> last_time
0.2909998893737793

while on Julia 1.7.0-rc3 VS Code REPL, there is a stack overflow for a much smaller matrix :

julia> exp(rand(50,50))
ERROR: StackOverflowError:

That looks like
https://github.com/julia-vscode/julia-vscode/issues/2543
https://github.com/JuliaLang/julia/issues/43008

1 Like