@profview not defined - REPL not connected to VSCode

I´m running Julia inside a VSCode devcontainer.

I open a new bash window and do:

julia
julia> using Main: @profview
ERROR: UndefVarError: @profview not defined

but if I start the REPL using VSCode’s command palette command Julia: Start REPL then:

julia> using Main: @profview
julia>

I´m running all of my Julia code from a Makefile. How can I start a Julia REPL from bash and have my code use Julia’s VSCode profiler?

There is an option “Connect to external REPL” (you can find it in the command palette), which gives you some code to connect any REPL to VS code (on the same machine). You can run your bash script and wait for some input from the user to paste in that code and then use eval to run it.

It’s not the most automated solution but I think it would work.

1 Like

You can also add ProfView to your main environment (similarly to recomendations for Revise or BenchmarkTools) and then they will be available in Julia from everywhere.

1 Like

Thank you for the reply. The code generated by Julia: Connect to external REPL is:

pushfirst!(LOAD_PATH, raw"/root/.vscode-server/extensions/julialang.language-julia-1.7.12/scripts/packages");using VSCodeServer;popfirst!(LOAD_PATH);VSCodeServer.serve(raw"/tmp/vsc-jl-repl-35432058-03a7-41cb-92af-db7da7f746af"; is_dev = "DEBUG_MODE=true" in Base.ARGS, crashreporting_pipename = raw"/tmp/vsc-jl-cr-8c4d1f53-ac71-437b-9432-63dc8cd7686e");nothing # re-establishing connection with VSCode

This works the the first time but unfortunately the generated path:

/tmp/vsc-jl-repl-35432058-03a7-41cb-92af-db7da7f746af

changes every time the devcontainer is rebuilt or even opened locally and reopened as a container. Each of those times I manually call Julia: Connect to external REPL from the command palette to get a new path that works, that I then manually change in the makefile, which defeats the purpose of the makefile.

Ideally Julia:Connect to external REPL would also give me the code that generates the tmp path and I would paste that in the makefile.

One other thing, is that if I run the generated code twice form the same terminal without reopening the devcontainer, the second time it will fail. For context, say my makefile command looks like this:

runjob:
	STAGE=Development  cd /app; julia --project=. -e ' \
	pushfirst!(LOAD_PATH, raw"/root/.vscode-server/extensions/julialang.language-julia-1.7.12/scripts/packages");using VSCodeServer;popfirst!(LOAD_PATH);VSCodeServer.serve(raw"/tmp/vsc-jl-repl-878d7a8e-1411-415e-8e8f-620dbac3de02"; is_dev = "DEBUG_MODE=true" in Base.ARGS, crashreporting_pipename = raw"/tmp/vsc-jl-cr-6100a566-74f1-48c5-9426-d97851c81be4");nothing # re-establishing connection with VSCode; \
	using Pkg; include("src/tests/run_mock_job.jl")'

The first time I do make runjob after pasting the code from Julia:Connect to external REPL it will work but then If I do make runjob again the VSCodeServer.serve(…) gives me this error:

ERROR: IOError: connect: no such file or directory (ENOENT)
Stacktrace:
 [1] wait_connected(x::Base.PipeEndpoint)
   @ Sockets /usr/local/julia/share/julia/stdlib/v1.8/Sockets/src/Sockets.jl:529
 [2] connect
   @ /usr/local/julia/share/julia/stdlib/v1.8/Sockets/src/Sockets.jl:564 [inlined]
 [3] connect
   @ /usr/local/julia/share/julia/stdlib/v1.8/Sockets/src/PipeServer.jl:103 [inlined]
 [4] serve(args::String; is_dev::Bool, crashreporting_pipename::String)
   @ VSCodeServer ~/.vscode-server/extensions/julialang.language-julia-1.7.12/scripts/packages/VSCodeServer/src/VSCodeServer.jl:110
 [5] top-level scope
   @ none:2

Nonetheless, thanks for your reply

Hi and thanks for the reply.

I initially tried adding ProfView.jl before considering VSCode’s profiler but was not able to use it due to errors related to the Gtk libraries. If I do:

]add ProfileView

 [3f19e933] + p7zip_jll v17.4.0+0
Precompiling project...
  ✗ GtkObservables
  ✗ ProfileView
  72 dependencies successfully precompiled in 24 seconds. 16 already precompiled.
  2 dependencies errored. To see a full report either run `import Pkg; Pkg.precompile()` or load the packages

import Pkg; Pkg.precompile()

Precompiling project...
  ✗ GtkObservables
  ✗ ProfileView
  0 dependencies successfully precompiled in 6 seconds. 88 already precompiled.

ERROR: The following 1 direct dependency failed to precompile:

ProfileView [c46f51b8-102a-5cf2-8d2c-8597cb0e0da7]

Failed to precompile ProfileView [c46f51b8-102a-5cf2-8d2c-8597cb0e0da7] to /root/.julia/compiled/v1.8/ProfileView/jl_wgJOiB.

(process:2845): Gtk-WARNING **: 15:49:01.206: Locale not supported by C library.
        Using the fallback 'C' locale.
ERROR: LoadError: InitError: Cannot open display: 
Stacktrace:
  [1] error(s::String)
    @ Base ./error.jl:35
  [2] Gtk.GLib.GError(f::Gtk.var"#329#338")
    @ Gtk.GLib ~/.julia/packages/Gtk/OyCvN/src/GLib/gerror.jl:17
  [3] __init__()
    @ Gtk ~/.julia/packages/Gtk/OyCvN/src/Gtk.jl:158
  [4] _include_from_serialized(pkg::Base.PkgId, path::String, depmods::Vector{Any})
    @ Base ./loading.jl:831
  [5] _require_search_from_serialized(pkg::Base.PkgId, sourcepath::String, build_id::UInt64)
    @ Base ./loading.jl:1039
  [6] _require(pkg::Base.PkgId)
    @ Base ./loading.jl:1315
  [7] _require_prelocked(uuidkey::Base.PkgId)
    @ Base ./loading.jl:1200
  [8] macro expansion
    @ ./loading.jl:1180 [inlined]
  [9] macro expansion
    @ ./lock.jl:223 [inlined]
 [10] require(into::Module, mod::Symbol)
    @ Base ./loading.jl:1144
 [11] include
    @ ./Base.jl:419 [inlined]
 [12] include_package_for_output(pkg::Base.PkgId, input::String, depot_path::Vector{String}, dl_load_path::Vector{String}, load_path::Vector{String}, concrete_deps::Vector{Pair{Base.PkgId, UInt64}}, source::Nothing)
    @ Base ./loading.jl:1554
 [13] top-level scope
    @ stdin:1
during initialization of module Gtk
in expression starting at /root/.julia/packages/ProfileView/S6A1N/src/ProfileView.jl:1
in expression starting at stdin:1
Stacktrace:
 [1] pkgerror(msg::String)
   @ Pkg.Types /usr/local/julia/share/julia/stdlib/v1.8/Pkg/src/Types.jl:67
 [2] precompile(ctx::Pkg.Types.Context, pkgs::Vector{String}; internal_call::Bool, strict::Bool, warn_loaded::Bool, already_instantiated::Bool, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ Pkg.API /usr/local/julia/share/julia/stdlib/v1.8/Pkg/src/API.jl:1427
 [3] precompile
   @ /usr/local/julia/share/julia/stdlib/v1.8/Pkg/src/API.jl:1058 [inlined]
 [4] #precompile#225
   @ /usr/local/julia/share/julia/stdlib/v1.8/Pkg/src/API.jl:1057 [inlined]
 [5] precompile (repeats 2 times)
   @ /usr/local/julia/share/julia/stdlib/v1.8/Pkg/src/API.jl:1057 [inlined]
 [6] top-level scope
   @ REPL[1]:1

At some point If I recall correctly I had solved the problem with the C locale but then I was getting another error related to the Gtk libraries, which seemed hard to solve, at which point I considered the VSCode profiler. Otherwise I would be using ProfileView.jl

Yes, I thought this would be the issue, and not an ideal solution.

As a question, can you use the normal Profiler @profile (which is what @profview does internally) and then save to a file (using Profile.print) and then use one of the options listed here to view this file after the fact?

As a tip, you can use something like @which @profview sum(1:10) in your REPL to find the files that define these functions and you can see that they don’t really even do much. I wasn’t able to find a function that loads a saved profile, but it seems like you could add it, but that seems like too far to go.

1 Like

You might wanna try ProfileCanvas.jl – it’s very similar to the VS Code profiler, but lacks some of the more advanced editor integration.

1 Like

Alright, so I can save the profile data to a file as in the docs:

open("/tmp/prof.txt", "w") do s
    Profile.print(IOContext(s, :displaysize => (24, 500)))
end

But I haven’t found a way to open the prof.txt file using one of the recommended profilers. Maybe I´m missing something.

Thanks for the suggestion. I have just tried Profile Canvas but haven’t been able to use it inside the devcontainer, neither with code running from a file/script.

First I tried from the REPL, inside the devcontainer:

julia> function profile_test(n)
              for i = 1:n
                  A = randn(100,100,20)
                  m = maximum(A)
                  Am = mapslices(sum, A; dims=2)
                  B = A[:,:,5]
                  Bsort = mapslices(sort, B; dims=1)
                  b = rand(100)
                  C = B.*b
              end
          end
profile_test (generic function with 1 method)

julia> using ProfileCanvas
julia> ProfileCanvas.@profview profile_test(10)

This initially did not work due to an error related to not being able to open the html file, it said something like “could not spawn xdg-open …” or similar.
I then added this to my dockerfile and rebuilt the devcontainer:

RUN apt-get install xdg-utils -y

If I run the same thing now I get a windows pop-up that says:
“You’ll need a new app to open this vscode-remote link” “Look for an app in the microsoft store” “Always use this app” (I think Windows users know this pop up)

If I run the same code from a file, inside the devcontainer (which is my intended use), the code will run to the end without attempting to show any profiling window or even generating the html file inside /tmp

If I run the code from a file, outside the devcontainer, it runs to the end without showing any profiling window neither.

If I run the code from the REPL outside the devcontainer it does work.

Try that one, it dumps an html page that you can browse in a browser

1 Like

Right, that’s not really expected to work. You just need to generate the HTML file with ProfileCanvas and open that later.

adds a convenience function for that.

1 Like

The thing is that running from a file/script i cannot generate the html file in the first place

This works for my usecase. Thank you