Codon: A high-performance Python Compiler

Python Codon | 3 minutes (about 608 words) | Sept 2, 2023

What is Codon?

Codon is a high-performance Python compiler that compiles Python code to native machine code without any runtime overhead. Typical speedups over Python are on the order of 100x or more, on a single thread. Codon supports native multithreading which can lead to speedups many times higher still.[1] It uses the LLVM framework to compile to LLVM bytecode and then to specific machine code.[2]


In simple terms, it is Python but compiled.


I first learned about Codon from an episode of C++ Weekly by Jason Turner (Ep 366 - C++ vs Compiled Python (Codon)) where he compares the performance of Python, C++, Python (jit), Python with C++ (cppyy) and Codon along with his Ep 362. He compares the performance by running his version of Conway’s game of life.


Since then, I worked with Codon for the first time during my internship at Viant. I worked on a POC where I improved the performance of their Python scripts by 30x on average on a single thread.


Installing Codon

These installation steps would be specific to macOS (arm64) and may not work in every case

- Installing pre-built binaries

# Execute the following command (from https://github.com/exaloop/codon#install)
# Press "y" to add Codon to PATH during installation
/bin/bash -c "$(curl -fsSL https://exaloop.io/install.sh)"

- Setting CODON_PYTHON environment variable

We need to set the CODON_PYTHON env var to point to the appropriate Python shared library. On macOS with a brew-installed python, this shared library can be something similar to -


/opt/homebrew/Cellar/python@3.11/3.11.3/Frameworks/Python.framework/Versions/3.11/lib/libpython3.11.dylib

# Run this command to find the base path of Python.framework
brew ls python3

Once found, set the env variable in the shell configuration file (~/.zshrc by default). Add the following line to the end of the file -


export CODON_PYTHON=<path-to-dylib-python-file>

Basics

If you know Python, you already know 99% of Codon. You can start using Codon directly, while keeping some differences in mind -

  1. In most cases you need to explicitly specify data types. In cases where you do not specify the data type and Codon cannot infer the type, it will treat as a Generic Python Object (PyObj)
def add(x: int, y: int) -> int:
    return x + y
  1. It’s best to keep the collections homogeneous or specifying the types during compile-time
t: tuple[str, int, bool]
t = ("abc", 1, False)

l: list[str] = [] # homogeneous lists
l.append("xyz")
  1. Once the CODON_PYTHON env var is set, you can import Python libraries using from python import
from python import numpy as np

Building/Running Codon files

By default, the codon run command compiles and runs in the DEBUG mode. To compile and run with optimizations -


codon run --release <path-to-codon-file>

To build executables use the codon build command -


codon build --release -o <exec-name> <path-to-codon-file>

Python vs. Codon

To compare the Python vs. Codon performance, we will use the following code to calculate the 40th fibonacci number. This can be found in the documentation.

# fib.py

from time import time

def fib(n):
    return n if n < 2 else fib(n - 1) + fib(n - 2)

t0 = time()
ans = fib(40)
t1 = time()
print(f'Computed fib(40) = {ans} in {t1 - t0} seconds.')
Python vs. Codon - fib.py
Comparing Python and Codon's performance by calculating the 40th fibonacci

From the above screenshot, we can see that Codon is ~38x faster than Python!

Conclusion

Working with Codon is really exciting. To have the syntax of Python and such improved performance is amazing. There are many other features that Codon has - native multithreading (no GIL!!), extending classes (including built-in classes like int, str), the @python decorator, and many more. I might explore more features in other posts related to Codon.

References

[1] https://docs.exaloop.io/codon

[2] https://medium.com/intuition/codon-a-python-compiler-3d5322e1c0a5

Home  |  /til/ Github Linkedin Email Resume Website Hugo theme by Yukuro