Writing Performant Code in Julia
techytok.ml
techytok.ml
"the type of the returned value of a function must depend only on the type of the input of the function and not on the peculiar value it is given." Fortran mandates this.
"Another common error is changing the type of a variable inside a function." Static typing, as in Fortran, disallows this.
"When a function is in a critical inner loop, avoid keyword arguments and use only positional arguments, this will lead to better optimisation and faster execution." I doubt this will matter for a compiled language.
"Avoid global scope variables." For a compiled language, it is unlikely to matter.
About the third point, it really won't matter in most other languages since in this case the Julia compiler is actually optimizing beyond those thanks to the multiple dispatch paradigm (in some cases it will even replace the function call directly with the result if it can solve it entirely with compile time information). And global variables in general can't be optimized by the compiler since they can be modified at any point, so it can't make any assumptions about it.
In julia, you optimize your code by just writing slightly uglier julia code, not leaving the language. This has huge implications for
1) People 'looking under the hood'. Instead of having to read C as well as Julia, they only need to read Julia (albeit, more advanced, ugly technical julia code). This tends to greatly lower the bar for a julia user to become a julia developer and actively encourages learning more about the language.
2) Programs 'looking under the hood'. Code modification, injection and re-use is really common in julia and is part of what makes writing it so magical. Part of that is multiple dispatch code: https://www.youtube.com/watch?v=kc9HwsxE1OY but another major thing this enables is prevalent language wide automatic differentiation tools. Julia users tend to take it for granted at this point that they can take just about any function which takes in a number and spits out a number and then take a derivative of that code at compile time, no matter if that function was ever written with auto-diff in mind or if it ever knew about tools like Zygote or Forward diff. This sort of stuff would not be nearly as powerful in a language which did a lot of calling out to other languages to achieve performance.
The entire idea of julia is trying to get as much expressiveness and dynamism as possible while still allowing for C/Fortran levels of speed.
A program that otherwise takes 4 seconds to compile and run takes 30 seconds when I also let it export a diagram, because each time I run "julia file.jl" it recompiles the plotting library. If there is a way to have a Julia runtime in the background and letting it execute iterations of the program I haven't found it yet.
The compiler team is prioritizing the compile-time latency and error messages for the 1.4 release, which if they succeed will make the language more approachable for people who use the same workflow as other dynamic languages (running the code from the shell).
~ time julia -e "using Plots; x = 0:0.01:10; plot(x, sin.(x))"
real 0m18.050s
user 0m17.466s
sys 0m0.321s
~ time julia --compile=min -e "using Plots; x = 0:0.01:10; plot(x, sin.(x))"
real 0m4.262s
user 0m3.706s
sys 0m0.263s