Speed of plotting using PlotlyJS

Is it normal that plotting using PlotlyJS takes 2-5 sec?

using PlotlyJS
plot(heatmap(z = rand(2000, 1000)))

Hi @Oto_Brzobohaty this is expected.

The vast majority of the time it taken up converting the large (2000, 1000) matrix to a nested JSON array to emebd in the WebIO scope. We would love to use a binary transport between julia and the web frontend, but that has yet to be implemented.

See below. 3526/5086 and then again another 1441/5086 of the traces are taken inside @JSON/src/Writer.jl for a total of 4967/5086, or ~97%

See the very end for the pure Julia side where I use Plot instead of plot. Depending on what you are trying to do with the plot, you might be able to get away with just Plot.

julia> using PlotlyJS

julia> using Profile

julia> @time plot(heatmap(z=rand(2000, 1000)));
  2.669931 seconds (8.99 M allocations: 1.276 GiB, 7.95% gc time)

julia> @time plot(heatmap(z=rand(2000, 1000)));
  0.966190 seconds (4.00 M allocations: 1.014 GiB, 11.70% gc time)

julia> @time rand(2000, 1000);
  0.002154 seconds (2 allocations: 15.259 MiB)

julia> Profile.@profile for i in 1:5 plot(heatmap(z=rand(2000, 1000))); end

julia> Profile.print()
Overhead β•Ž [+additional indent] Count File:Line; Function
=========================================================
    β•Ž5086 @Base/client.jl:506; _start()
    β•Ž 5086 @Base/client.jl:313; exec_options(::Base.JLOptions)
    β•Ž  5086 @Base/client.jl:383; run_main_repl(::Bool, ::Bool, ::Bool, ::Bool, ::Bool)
    β•Ž   5086 @Base/essentials.jl:709; invokelatest
    β•Ž    5086 @Base/essentials.jl:710; #invokelatest#1
    β•Ž     5086 @Base/client.jl:399; (::Base.var"#806#808"{Bool,Bool,Bool,Bool})(::Module)
    β•Ž    β•Ž 5086 ...e_linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:288; run_repl(::REPL.AbstractREPL, ::Any)
    β•Ž    β•Ž  5086 ..._linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:292; run_repl(::REPL.AbstractREPL, ::Any; backend_on_current_task::Bool)
    β•Ž    β•Ž   5086 ..._linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:180; start_repl_backend(::REPL.REPLBackend, ::Any)
    β•Ž    β•Ž    5086 ..._linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:195; repl_backend_loop(::REPL.REPLBackend)
    β•Ž    β•Ž     5086 ...linux64/build/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:134; eval_user_input(::Any, ::REPL.REPLBackend)
    β•Ž    β•Ž    β•Ž 5086 @Base/boot.jl:331; eval(::Module, ::Any)
    β•Ž    β•Ž    β•Ž  5086 ...4/build/usr/share/julia/stdlib/v1.5/Profile/src/Profile.jl:28; top-level scope
    β•Ž    β•Ž    β•Ž   5086 REPL[7]:1; macro expansion
    β•Ž    β•Ž    β•Ž    22   ...64/build/usr/share/julia/stdlib/v1.5/Random/src/Random.jl:277; rand
    β•Ž    β•Ž    β•Ž     22   ...4/build/usr/share/julia/stdlib/v1.5/Random/src/Random.jl:289; rand(::Type{Float64}, ::Tuple{Int64,Int64})
    β•Ž    β•Ž    β•Ž    β•Ž 22   ...4/build/usr/share/julia/stdlib/v1.5/Random/src/Random.jl:288; rand
    β•Ž    β•Ž    β•Ž    β•Ž  15   @Base/boot.jl:423; Array
    β•Ž    β•Ž    β•Ž    β•Ž   15   @Base/boot.jl:416; Array
  15β•Ž    β•Ž    β•Ž    β•Ž    15   @Base/boot.jl:408; Array
    β•Ž    β•Ž    β•Ž    β•Ž  7    .../build/usr/share/julia/stdlib/v1.5/Random/src/Random.jl:267; rand!
    β•Ž    β•Ž    β•Ž    β•Ž   7    ...64/build/usr/share/julia/stdlib/v1.5/Random/src/RNGs.jl:513; rand!
    β•Ž    β•Ž    β•Ž    β•Ž    7    ...64/build/usr/share/julia/stdlib/v1.5/Random/src/RNGs.jl:507; _rand!
    β•Ž    β•Ž    β•Ž    β•Ž     7    ...4/build/usr/share/julia/stdlib/v1.5/Random/src/RNGs.jl:495; rand!(::Random.MersenneTwister, ::Random.UnsafeView{Float64}, ::Random.SamplerTrivi...
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž 7    ...4/build/usr/share/julia/stdlib/v1.5/Random/src/RNGs.jl:469; fill_array!
   6β•Ž    β•Ž    β•Ž    β•Ž    β•Ž  7    .../build/usr/share/julia/stdlib/v1.5/Random/src/DSFMT.jl:95; dsfmt_fill_array_close_open!(::Random.DSFMT.DSFMT_state, ::Ptr{Float64}, ::Int64)
    β•Ž    β•Ž    β•Ž    5064 @PlotlyJS/src/display.jl:145; plot
    β•Ž    β•Ž    β•Ž     5064 @PlotlyJS/src/display.jl:145; #plot#6
    β•Ž    β•Ž    β•Ž    β•Ž 5064 @PlotlyJS/src/display.jl:24; Type##kw
    β•Ž    β•Ž    β•Ž    β•Ž  6    @PlotlyJS/src/display.jl:47; PlotlyJS.SyncPlot(::Plot{Array{GenericTrace{Dict{Symbol,Any}},1},Layout{Dict{Symbol,A...
    β•Ž    β•Ž    β•Ž    β•Ž   6    @WebIO/src/scope.jl:224; setindex!
    β•Ž    β•Ž    β•Ž    β•Ž    6    @WebIO/src/scope.jl:185; setobservable!
    β•Ž    β•Ž    β•Ž    β•Ž     6    @WebIO/src/scope.jl:195; setobservable!(::WebIO.Scope, ::String, ::Observables.Observable{String}; sync::Not...
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž 6    @Base/weakkeydict.jl:82; setindex!
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž  6    @Base/weakkeydict.jl:76; lock
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž   6    @Base/lock.jl:161; lock(::Base.var"#507#508"{WeakKeyDict{Any,Any},Tuple{WeakRef,String},Observables....
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    6    @Base/weakkeydict.jl:83; #507
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž     6    @Base/dict.jl:381; setindex!(::Dict{WeakRef,Any}, ::Tuple{WeakRef,String}, ::WeakRef)
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž 6    @Base/dict.jl:326; ht_keyindex2!(::Dict{WeakRef,Any}, ::WeakRef)
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž  6    @Base/operators.jl:123; isequal
   6β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž   6    @Base/gcutils.jl:3; ==(::WeakRef, ::WeakRef)
    β•Ž    β•Ž    β•Ž    β•Ž  5058 @PlotlyJS/src/display.jl:78; PlotlyJS.SyncPlot(::Plot{Array{GenericTrace{Dict{Symbol,Any}},1},Layout{Dict{Symbol,A...
    β•Ž    β•Ž    β•Ž    β•Ž   2    @Base/strings/substring.jl:191; string(::String, ::String, ::Vararg{String,N} where N)
   2β•Ž    β•Ž    β•Ž    β•Ž    2    @Base/strings/string.jl:60; _string_n
    β•Ž    β•Ž    β•Ž    β•Ž   37   @Base/strings/substring.jl:194; string(::String, ::String, ::Vararg{String,N} where N)
    β•Ž    β•Ž    β•Ž    β•Ž    37   @Base/strings/substring.jl:178; __unsafe_string!
  37β•Ž    β•Ž    β•Ž    β•Ž     37   @Base/array.jl:245; unsafe_copyto!
    β•Ž    β•Ž    β•Ž    β•Ž   3526 @JSExpr/src/JSExpr.jl:19; jsexpr(::Array{GenericTrace{Dict{Symbol,Any}},1})
    β•Ž    β•Ž    β•Ž    β•Ž    3526 @Base/strings/io.jl:101; sprint
    β•Ž    β•Ž    β•Ž    β•Ž     3526 @Base/strings/io.jl:105; sprint(::Function, ::Array{GenericTrace{Dict{Symbol,Any}},1}; context::Nothing, siz...
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž 3526 @JSExpr/src/JSExpr.jl:20; (::JSExpr.var"#1#2")(::Base.GenericIOBuffer{Array{UInt8,1}}, ::Array{GenericTrace{D...
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž  3526 @JSON/src/Writer.jl:324; show_json
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž   3526 @JSON/src/Writer.jl:325; #show_json#3
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    3526 @JSON/src/Writer.jl:293; show_json(::JSON.Writer.CompactContext{Base.GenericIOBuffer{Array{UInt8,1}}}, ::W...
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž     3526 @JSON/src/Writer.jl:218; show_element(::JSON.Writer.CompactContext{Base.GenericIOBuffer{Array{UInt8,1}}},...
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž 3526 @JSON/src/Writer.jl:314; show_json
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž  3526 @JSON/src/Writer.jl:271; show_json(::JSON.Writer.CompactContext{Base.GenericIOBuffer{Array{UInt8,1}}}, :...
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž   3526 @JSON/src/Writer.jl:243; show_pair(::JSON.Writer.CompactContext{Base.GenericIOBuffer{Array{UInt8,1}}}, ...
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    3526 @JSON/src/Writer.jl:241; show_pair(::JSON.Writer.CompactContext{Base.GenericIOBuffer{Array{UInt8,1}}}, ...
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž     3526 @JSON/src/Writer.jl:306; show_json(::JSON.Writer.CompactContext{Base.GenericIOBuffer{Array{UInt8,1}}},...
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž 3526 @JSON/src/Writer.jl:218; show_element(::JSON.Writer.CompactContext{Base.GenericIOBuffer{Array{UInt8,1...
   1β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž  1    @JSON/src/Writer.jl:215; show_element(::JSON.Writer.CompactContext{Base.GenericIOBuffer{Array{UInt8,1...
   3β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž  3    @JSON/src/Writer.jl:218; show_element(::JSON.Writer.CompactContext{Base.GenericIOBuffer{Array{UInt8,1...
  13β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž  3522 @JSON/src/Writer.jl:293; 

XXXXXXXXXX MANY LINES DELETED!

    β•Ž    β•Ž    β•Ž    β•Ž   1493 @WebIO/src/scope.jl:313; onimport
    β•Ž    β•Ž    β•Ž    β•Ž    1493 @Base/strings/io.jl:101; sprint
    β•Ž    β•Ž    β•Ž    β•Ž     1493 @Base/strings/io.jl:105; sprint(::Function; context::Nothing, sizehint::Int64)
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž 1493 @WebIO/src/syntax.jl:221; (::WebIO.var"#42#43"{WebIO.Scope,WebIO.JSString})(::Base.GenericIOBuffer{Array{UIn...

XXXXXXXXXX MANY LINES DELETED!


    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž  1492 @WebIO/src/syntax.jl:193; showjs
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž   1492 @JSON/src/Writer.jl:324; show_json
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    1492 @JSON/src/Writer.jl:325; #show_json#3
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž     1492 @WebIO/src/syntax.jl:246; show_json(::JSON.Writer.CompactContext{Base.GenericIOBuffer{Array{UInt8,1}}}, ::...
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž 1492 @Base/strings/io.jl:185; print
   1β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž  1492 @Base/strings/io.jl:183; write
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž   1491 @Base/io.jl:233; unsafe_write(::JSON.Writer.CompactContext{Base.GenericIOBuffer{Array{UInt8,1}}...
   3β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    5    @Base/pointer.jl:105; unsafe_load
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž     2    @Base/boot.jl:708; Int64
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž 2    @Base/boot.jl:633; toInt64
   2β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž  2    @Base/boot.jl:572; check_top_bit
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    45   @Base/range.jl:624; iterate
  45β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž     45   @Base/promotion.jl:398; ==
    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    β•Ž    1441 @JSON/src/Writer.jl:122; write

XXXXXXXXXX MANY LINES DELETED!



Total snapshots: 5095

julia> @time Plot(heatmap(z=rand(2000, 1000)));
  0.003693 seconds (23 allocations: 15.261 MiB)
4 Likes

Thank you for the clarification. Typically, I use VS Code with plot pane and the plotting is very slow. The plot command is done and the profile gives me st like this

@time Plot(heatmap(z = rand(2000, 1000)))
  0.006809 seconds (22 allocations: 15.261 MiB)

But the plotting either in VS Code Plot pane or electron window takes 2-5 secs.

Generating the plot itself (or at least the heatmap for it) is strictly fast (e.g. if you would only want to get it to a file). PlotlyJS is web technology, but you’re not displaying it in a web browser that’s already open. The wrapper, uses Blink, that starts a GUI for you, while not obvious is a full web browser, that’s the thing taking time to start (the first time each time), and that’s at least part of the problem.

https://juliahub.com/ui/Packages/Blink/wSmkt/0.12.3?t=0

That’s (kind of) what’s meant by the docs saying:

This package does not interact with the Plotly web API, but rather leverages the underlying javascript library to construct plotly graphics using all local resources.

Using some other plotting package that converts to a picture, not JSON, might be what you need to speed this up.

I use Julia 1.6, and depending on options this is the speed:

$ julia -O1 -q
julia> @time using Plots
  4.253229 seconds (5.80 M allocations: 414.695 MiB, 2.36% gc time)

julia> @time plot(heatmap(z = rand(2000, 1000)))
  1.185529 seconds (1.20 M allocations: 84.774 MiB, 5.22% gc time)

[I’m having trouble on my machine with GR.jl, that’s the default backend for above, making it hang. I think, I’m not sure, you would see something with above, this fast.]

I didn’t find the best Plots.jl backend (or look much further) to actually see the plot (and the first plot/heatmap is going to be the slowest):

$ julia -O0 --compile=min -q
julia> @time using Plots
  3.606296 seconds (5.12 M allocations: 376.402 MiB, 2.88% gc time)

julia> @time heatmap(z = rand(2000, 1000));
  0.228301 seconds (128.01 k allocations: 23.188 MiB, 33.66% gc time)

julia> @time heatmap(z = rand(2000, 1000));
  0.034798 seconds (5.44 k allocations: 15.436 MiB)

This seemed to work (did you get similar?), note, deprecations are known to slow down Julia:

julia> using PlotlyJS
[ Info: Precompiling PlotlyJS [f0f68f2c-4968-5e81-91da-67840de0976a]
β”Œ Warning: `@get!(dict, key, default)` at /home/pharaldsson_sym/.julia/packages/WebIO/nTMDV/src/scope.jl:160 is deprecated, use `get!(()->default, dict, key)` instead.
β”” @ Base deprecated.jl:204
β”Œ Warning: `@get!(dict, key, default)` at /home/pharaldsson_sym/.julia/packages/WebIO/nTMDV/src/scope.jl:357 is deprecated, use `get!(()->default, dict, key)` instead.
β”” @ Base deprecated.jl:204
WARNING: using HTTP.stack in module Mux conflicts with an existing identifier.

Is there any way how to improve drawing speed in VSCode plot pane?

Usually, I have plotted several graphs and even deleting them is very slow.

@Oto_Brzobohaty could you do an experiment for us?

Can you try using PlotlyBase for plotting in vs code instead of PlotlyJS? (note you’ll need to use Plot with a capital P instead of plot after using PlotlyBase - other than that everything should be the same)

After doing that can you report to see if it is still slow?

1 Like

Is this what do you need?

https://youtu.be/JHQYgFvl5i0