liveBook · Manning

Just-in-time compilation

As explained in Julia as a Second Language

A just-in-time compiler compiles program code into executable machine code during program execution.

Julia can start more slowly than a short Python or Bash script, then run much faster after critical code has been compiled. That trade-off comes from just-in-time (JIT) compilation: turning code into machine code while the program runs. section 1.7

The timing distinguishes JIT compilation from ahead-of-time compilation, which translates a program before it runs, and interpretation, which processes source instructions at runtime. Julia was designed for JIT compilation, though a language is not inherently limited to one execution method. section 1.1.1

JIT compilation helps Julia combine dynamic typing with high performance. When Julia generates code for a method, it knows the input argument types. Because an object's fields are fixed by its type, the compiler can use that information to generate optimized machine code. Multiple dispatch is another part of this design. section 1.1.1 section 18.4

Listing 18.10 Vec2D defined with abstract type fields to mimic regular dynamic languages
struct Vec2D         #1
    Δx::Number       #2
    Δy::Number       #2
end
 
function multiply(u::Vec2D, k::Number)
    Vec2D(k * u.Δx, k * u.Δy)
end

Inspect the Vec2D definition and its multiply method. Its fields are declared as Number, providing a concrete starting point for thinking about the type information available during compilation. section 18.4

Listing 18.11 Pseudocode of how multiply would work in a normal dynamic language
function multiply(u::Vec2D, k::Number)
    ux = getfield(u, :Δx)
    if !isa(ux, Float64)
        error("x must be a float")
    end
 
    uy = getfield(u, :Δy)
    if !isa(uy, Float64)
        error("y must be a float")
    end
 
    c = convert(Float64, k)
    Vec2D(floatmul(c, ux), floatmul(c, uy))
end

Compare the illustrative pseudocode for a conventional dynamic-language approach: it looks up fields and checks their types at runtime. It is not a listing of Julia's generated code. section 18.4

The practical question is whether the work after compilation outweighs the startup delay. JIT compilation makes Julia less attractive for some small, short-running scripts; caching previous compilations and compiling more selectively are cited approaches to reducing that cost. section 1.7

How Julia as a Second Language covers it

How deep it goes
Defines compilation timing and explains type-informed optimization, but does not walk through generated machine code.
Examples
Uses short Python and Bash scripts to illustrate startup costs and a Vec2D method to illustrate runtime type-checking overhead.
What it assumes
Introduces compilation and interpretation in plain terms; uses familiarity with methods and types for the optimization example.
What you can do after
Evaluate/understand it when weighing Julia's faster post-compilation execution against slower startup for short scripts.
How it connects
Connects JIT compilation to dynamic typing, multiple dispatch, ahead-of-time compilation, interpretation, and parametric types.

Also explained in

Compare how 7 books explain just-in-time compilation →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Julia as a Second Language. The section links point to the parts of the book it draws on.