Ensure Julia is used to its full power

Thanks for the tip, but my problem with Jupyter is at another level. I first thought that I could host a notebook on the web, share it with students, and that students could open it and have it running right away. This is not the case, because when the students try to load the project the packages start to be installed, and that can take a lot of time. Worst, depending on how the student save the work done, every time he/she loads the notebook everything starts again. I suppose you are referring to launching Jupyter from whithin Julia. In that case I do not see many advantages in relation to share a code directly, except for some pretty formatting.

That would be really great for portability actually, so returning back to my example where I would make a Julia program and then plot something using Plots.jl I would just send the whole source code and in the first run it would compile that package and on the next runs, regardless of how the user changes the file that performs the plot, it would not recompile Plots.jl?

You may also want to try Juno, which allows you to work in code cells like Jupyter, but works with plain .jl files, and has results showing either in inline pop-ups, in a REPL pane, or (for graphical results) in a plots pane. It’s similar in style to the MATLAB IDE, though unfortunately not quite as polished and responsive.
I find it more convenient than the Jupyter style of results under each cell. I usually use Juno+Revise with a “live” julia session in my everyday work, restarting Julia only occasionally.
There’s also a Julia plugin for VSCode, but that seems to be in a more preliminary stage of development at this point.

1 Like

Actually I have moved to VSCode from Juno. The original Juno developers now work on its Julia integration. It now has almost all the Juno functionality (especially in the Insiders Edition).

Juno is now in maintenance mode IIRC.

2 Likes

I don’t use vim but there’s things like

https://github.com/lambdalisue/jupyter-vim-binding

1 Like

Maybe you could exemplify where are you having these issues, so we are on the same page. For example, this code:

using Plots
x = sort(rand(100)); y = sort(rand(100));
scatter(x,y)
savefig("plot.png")

It takes 15 seconds in my laptop to run, with:

julia simpleplot.jl

(with Julia 1.6, to be released, it takes 10 seconds).

(a similar script in python takes 0.5 seconds)

That ~10 to 15 seconds is the delay associated to the “first plot” we are talking about. Certainly other scripting languages are faster to startup (for now, at least), but this is the “compilation time” that you will experience in everyday use, and that we claim that is irrelevant if what you are doing is a heavy calculation.

edit: On the very first time you use the package it gets compiled and it takes more time, but this occurs only when the package is installed or updated. I think that in Julia 1.6 they moved this first compilation to the installation process (which is something nice, because we are usually willing to wait some time upon package installation, but not so in its first use).

2 Likes

I suppose what counts as “almost all” depends on how you tend to use it. I haven’t tried the Insiders Edition, but based on the official release, at this point I would still recommend Juno. The VSCode plugin still misses some of what I would consider basic functionality for working with code cells, like commands for moving between cells, or executing a cell without moving to the next.

Okay I think I’m getting it, on the first run right after installing Plots I got, on your script:

$ time julia misc/j.jl
julia misc/j.jl  141.87s user 6.04s system 97% cpu 2:31.76 total

On the second and consecutive runs I got:

$ time julia misc/j.jl
julia misc/j.jl  20.74s user 0.48s system 94% cpu 22.490 total

This is on a laptop with a i5-7300HQ @ 2.50GHz (Max 3.50 GHz) Quad Core CPU. So what this means is that to compile and execute this rather small script takes about ≈ 20 seconds?

I also noticed Julia created some files over at ~/.julia which seems to include a lot of things and seems a little big. I’m assuming that this is the folder used to have my Julia environment and it has both the source files and compiled files of all the packages I’m using. I have a few questions regarding that:

  • Usually when I install a package on my system it’s already compiled, making the user download the source code and compile the package in it’s system would take up quite some space after a while of playing around. Can’t it be to download the binaries pre-compiled?
  • How do Julia environments work? Is it on a project based scenario where I would just keep a folder with all of my Julia files and in that folder I would include all of the source code of the modules I’m using, or does it always use the files over at ~/.julia?

I can see that this is a language which is still being worked on, and I really never took in consideration, like somebody previously mentioned here, the time, effort and money people took to develop these languages and make them usable and convenient to use for all sorts of people, so I’m probably asking something that has already been asked before around here or that is being worked on but I’m unsure where should I go to to keep tabs on what can or cannot be done (usually google always provides me with an answer in the first page when it’s something related to Python, Java or C++ with whatever issue I run into).

No I wasn’t, after looking at the documentation it seems to be the default file that is run when Julia is called, however it seems to be on the local environment .julia/config/startup.jl instead of a per project basis, which might make me load unnecessary stuff if I change the project I’m working on.

1 Like

One of the most valuable things about Julia as a language is the ability to substitute your own user-defined types into an external package, or to use types and methods from unrelated packages together without needing to write glue code. That requires the user’s Julia process to have access to the source code, without which it’d be impossible to compile new methods for the new combination of method & type. That means Julia packages are distributed with their source code (and often with compiled binaries for external dependencies - see Yggdrasil.jl).

This video is a great explanation for the vitality of multiple dispatch as a way to easily extend functionality from one domain to another: JuliaCon 2019 | The Unreasonable Effectiveness of Multiple Dispatch | Stefan Karpinski - YouTube

5 Likes

Yes, because it needs to compile some parts of Plots every time. This is the famous “time-to-first-plot” issue that is discussed and worked out continously.

There is where all the packages you install are stored. That is why that gets big with time.

Concerning the environments, I will let someone more comfortable speak about them. You can use different versions of a package (development version, for example), in different environments. That is what I use them for, but only with very basic functionality.

We do have Execute Cell and Execute Cell and Move. Also consider using the Juno-inspired keybindings to make the transition easier (although those might be the default in the next release).

But regardless, keep the feedback coming so we can better prioritize what to work on :wink:

2 Likes

But just to give you an idea. You can install that educational package I am developing, which I mentioned above, with:

] add https://github.com/m3g/CKP

and I didn’t even registered that package. It is just my github account with the data properly organized. Distributing a package is that simple.

If you type, then:

] dev CKP 

that will copy the github repository into .julia/dev/

The source code is there to be modified at will.

You can go that directory, cd .julia/dev/CKP

and do:

julia --project 

You will have launched a julia section with an environment in which the development version of that project is active.

If you then do:

using Revise
using CKP

and start playing with the functions there, the changes in those functions will be automatically updated in that same section, and you can develop and test the code at once.

And you can do that with EVERY Julia package (that one is not even a good example, I just wanted to show that to distribute it you only need a github account).

5 Likes

Even better, they can just git clone the repository into any directory they want, then run import Pkg; Pkg.instantiate(".").

This is most useful if they don’t need access to that package in their main environment, which is probably the case if it’s a “end product” project.

2 Likes

That is exactly what I wanted, to have a folder with everything required in it I could just move around without worrying if it were to break or not!

Ahhh, so it’s something unlike standard compile languages, where just having the binaries is more than enough to run the program, if you’re not making any changes to it, obviously. In this case the compiler always requires the source code because, for a given program you just wrote, it might require a given method, but changing just the type of a given variable that would be used in that method, would mean a change in the method used, and therefore would require a recompilation, right?

I didn’t know that that was a thing. Thanks!

Yes, let’s say for example I have some experimental measurements with accompanying uncertainty, where I’m using the Measurements.jl library to propagate that uncertainty through arbitrary Julia functions:

julia> using Measurements

julia> x = @. (1:5) ± randn()
5-element Vector{Measurement{Float64}}:
 1.0 ± -0.39
 2.0 ± 0.53
 3.0 ± 0.21
 4.0 ± -1.1
 5.0 ± 0.83

julia> y = @. x^2 + randn()/10
5-element Vector{Measurement{Float64}}:
 0.99 ± 0.79
  3.9 ± 2.1
  9.1 ± 1.3
 16.0 ± 8.5
 25.1 ± 8.3
julia> f(x, y) = sin(log(x))/maximum(y)
f (generic function with 1 method)

julia> f.(x, y)
5-element Vector{Measurement{Float64}}:
   0.0 ± 0.4
 0.163 ± 0.036
 0.098 ± 0.01
 0.061 ± 0.029
  0.04 ± 0.013

Now I want to fit a polynomial to my data, giving more weight to the data points with smaller uncertainty bands. I can use Polynomials.jl for generic polynomial types, and GenericLinearAlgebra.jl for the least-squares solution required for curve-fitting, even though none of these packages know about one another.

julia> using Polynomials, GenericLinearAlgebra

julia> fit(x, y, 2)
Polynomial(-0.067 ± 0.069 + 0.037 ± 0.055*x + 0.9987 ± 0.0088*x^2)
9 Likes

wow I didn’t know this would make 5 separate randn()

julia> @. (1:5) + rand()
5-element Array{Float64,1}:
 1.6943076223230025
 2.0840901393013587
 3.0642268315135643
 4.0458068854346525
 5.327237284126403

julia> (1:5) .+ rand() |> collect
5-element Array{Float64,1}:
 1.1849641778515916
 2.1849641778515916
 3.1849641778515916
 4.184964177851592
 5.184964177851592

2 Likes

Yep, you can broadcast zero-arg functions if they’re included in an expression with broadcasts of known size:

julia> (1:5) .+ randn()
1.789233870768912:1.0:5.789233870768912

julia> (1:5) .+ randn.()
5-element Vector{Float64}:
 1.684458186180139
 3.318040870638627
 3.367874919951659
 4.760440952027665
 5.330734112478098
4 Likes

Where did you get this?
Can you point to some place where this is discussed?