Compiler vs Interpreter vs JIT: Differences Explained
There are three main ways to run source code. A compiler (ahead-of-time, or AOT) translates the whole program into machine code before it runs. An interpreter reads and executes the program as it runs, without producing a separate machine-code file. A just-in-time (JIT) compiler starts by interpreting and then compiles the frequently used parts into machine code while the program is running. Many languages mix these approaches.
| Aspect | Compiler (AOT) | Interpreter | JIT compiler |
|---|---|---|---|
| When code is translated | Before running: the whole program becomes machine code | While running: the program is read and executed step by step | While running: frequently used code is compiled into machine code |
| Start-up | Fast to start (but needs a build step first) | Fast to start, with no build step | Slower at first, until the code is warmed up |
| Execution speed | Fastest and most predictable | Slowest, often many times slower than compiled code | Close to compiled speed after warm-up, sometimes faster by using run-time information |
| Portability | A binary for each platform | Portable: runs wherever the interpreter exists | Portable bytecode, with a platform-specific runtime |
| Error detection | Many errors are caught at compile time | Errors appear when the faulty line runs | Depends on the language |
| Memory use | Low run-time overhead | The interpreter itself stays in memory | Extra memory for the compiler and compiled-code cache |
| Development cycle | Edit, build, run | Edit and run immediately | Usually edit and run, or build to bytecode |
| Example languages | C, C++, Rust, Go | Classic Python (CPython), Ruby, shell scripts | Java (HotSpot), JavaScript (V8), C# (.NET), PyPy |
Figures are typical orders of magnitude and vary by process generation and product.