Python vs Mojo vs Rust: A Fibonacci Speed Test

Fibonacci Fever: A Speed Comparison of Python, Mojo, and Rust

Fibonacci Fever: A Speed Comparison of Python, Mojo, and Rust


STATPAN is cooking python, mojo, rust

Welcome to my blog, where I share my passion for coding and learning new things. In this post, I will show you how I measured the performance of three popular programming languages: Python, Mojo, and Rust, using the classic fibonacci sequence as a test case. I will also explain the pros and cons of each language and give you some tips on how to optimize your code. Let's get started!


Python


Python is a widely used and versatile programming language that comes pre-installed on many operating systems. To check if you have Python installed, open a terminal and type python --version. If you see a version number, you are good to go. If not, you can download and install Python from the official website. You can also use a package manager like apt or brew to install Python on Linux or macOS respectively. To install additional Python packages, you can use pip, which is a tool that comes with Python. For example, to install the numpy package, you can type pip install numpy in the terminal.

Python is one of the most popular and widely used programming languages in the world, especially for artificial intelligence and machine learning applications. Python has a large and active community, a rich set of libraries and frameworks, and a simple and expressive syntax that makes it easy to learn and use.

However, Python also has some drawbacks, such as its slow performance, its lack of static typing, and its difficulty in interfacing with low-level hardware. These limitations can hinder the development and deployment of complex and high-performance AI systems that require speed, efficiency, and reliability. Therefore, some developers are looking for alternatives to Python that can offer better performance and more features for AI programming.


Mojo


Mojo is a new programming language that claims to be 68,000 times faster than Python. Mojo is developed by Modular, a company that specializes in AI hardware and software solutions. Mojo is designed to be a superset of Python, meaning that it can run any valid Python code without modification. However, Mojo also adds some new features that make it more powerful and suitable for AI development, such as:

  • A progressive type system that allows the programmer to choose between dynamic and static typing, depending on the context and preference.
  • A zero-cost abstraction mechanism that enables the programmer to write high-level code without sacrificing performance or control over memory management.
  • A multi-level intermediate representation (MILR) that allows the programmer to manipulate the code at different levels of abstraction, from high-level Python-like syntax to low-level LLVM-like instructions.
  • A built-in concurrency model that supports parallel and distributed computing across multiple devices and platforms.
  • A seamless integration with popular AI frameworks such as TensorFlow and PyTorch, as well as Modular's own AI hardware products.

To install Mojo, you need to use the Modular CLI tool, which works like a package manager to install and update Mojo. You can get the Modular CLI tool from the Modular developer console, where you can also download the Mojo SDK. The Mojo SDK includes everything you need for local Mojo development, including the Mojo standard library and the Mojo command-line interface (CLI). The Mojo CLI can start a REPL programming environment, compile and run Mojo source files, format source files, and more. You can also use the Mojo extension for Visual Studio Code to provide a first-class developer experience with features like code completion, quick fixes, and hover help for Mojo APIs. To use the Mojo SDK, you need a system that meets these specifications: Ubuntu 20.04/22.04 LTS x86-64 CPU (with SSE4.2 or newer) and a minimum of 8 GiB memory; Python 3.8 - 3.10; g++ or clang++ C++ compiler. Support for Windows and macOS will be added in a future release.

Mojo aims to provide a unified programming model that works across levels of abstraction, from accelerators to application programming and scripting. It also strives to be friendly for novice programmers, while scaling across many use cases from machine learning to systems programming.


Rust


Rust is a fast and reliable programming language that empowers developers to build concurrent and secure systems. Rust is not usually installed by default on most operating systems, so you need to download and install it manually. The recommended way to install Rust is to use the rustup tool, which is a command-line tool that manages Rust versions and associated tools. You can get rustup from the official website, where you can also find instructions on how to install Rust on different platforms. Once you have rustup, you can use it to install the latest stable version of Rust by typing rustup install stable in the terminal. You can also use rustup to update Rust, switch between different versions, and install additional components like the Rust compiler (rustc), the Rust package manager (cargo), and the Rust standard library (std). To check if Rust is installed correctly, you can type rustc --version in the terminal.

Rust is designed to be a systems programming language that can handle low-level tasks such as operating systems, embedded systems, and web servers. However, Rust also has some features that make it appealing for AI development, such as:

  • A strong type system that prevents common errors such as null pointers, memory leaks, data races, and buffer overflows.
  • A powerful ownership model that ensures memory safety and concurrency safety without requiring garbage collection or runtime overhead.
  • A trait-based generics system that enables code reuse and abstraction without compromising performance or type safety.
  • A rich set of libraries and tools that provide functionality for various domains such as web development, data analysis, machine learning, cryptography, and more.

Rust aims to provide a language that empowers developers to build fast and reliable software without sacrificing expressiveness or ergonomics. It also strives to be a community-driven project that welcomes contributions from anyone who wants to improve the language or its ecosystem.

Rust and Mojo have some similarities in their syntax and features, such as their use of curly braces for blocks, their support for pattern matching and destructuring, their use of traits for polymorphism and abstraction, their use of LLVM for code generation and optimization, and their emphasis on performance and safety. However, they also have some differences in their design goals and trade-offs, such as their approach to dynamic versus static typing, their support for garbage collection versus manual memory management, their integration with existing Python code versus new AI frameworks and hardware products. Therefore, they may appeal to different kinds of developers depending on their preferences and needs.


Benchmarking Environment


To compare the speed of Python, Mojo, and Rust on the fibonacci sequence, I used the following environment.

  • container image: jupyter/datascience-notebook0530
  • Ubuntu 22.04
  • AMD Ryzen 9 5950X 16-Core Processor
  • python version: 3.10.11
  • modular version: 0.2.0
  • rustc version: 1.73.0

Benchmarking code


To compare the speed of Python, Mojo, and Rust on the fibonacci sequence, I used the following code.


Python


 import time

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

start = time.time()
result = fibonacci(40)
end = time.time() - start
print(result)
print(end)

Mojo


from time import now

fn fibo(n: Int) -> Int:
    if n <= 1:
        return n
    else:
        return fibo(n-1) + fibo(n-2)

fn main():
    let start = now()
    let result = fibo(40)
    let end = (now() - start) / 1000000000 # as sec
    print(result)
    print(end)

Rust


use std::time::Instant;

fn fibo(n:u128) -> u128 {
    if n <= 1 {
        return n
    } else {
        return fibo(n-1) + fibo(n-2)
    }
}

fn main() {
    let start = Instant::now();
    let result = fibo(40);
    let end = start.elapsed().as_secs();
    println!("{}",result);
    println!("{:?}",end);
}

Benchmarking Results

The following chart shows the average time (in seconds) it takes to compute the n-th fibonacci number in Python, Mojo, and Rust for different values of n:

python rust mojo fibo sequence benchmark

The following table shows the average time (in seconds) for each value of n in each language:

n Python Mojo Rust(u128) Rust(u64, release)
10 0.000012 0.0000003399 0.000000651(release 401) 0.000000330
20 0.001026 0.00002432 0.000059902(release 33824) 0.000015389
30 0.129870 0.001816 0.006889(release 2386) 0.001670
40 15.815232 0.2093219 0.8493370(release 2934151) 0.1995641
50 1935.739641 26.258969 106(release 36) 25.676754

As you can see from the chart and the table, Python is the slowest language among the three, followed by Mojo and Rust, which are very close in speed. The difference in performance becomes more noticeable as n increases, indicating that Python has a much higher computational complexity than Mojo and Rust for the fibonacci sequence.


There are several reasons why Python is slower than Mojo and Rust on the fibonacci sequence:

  • Python is an interpreted language, which means that it executes the code line by line without compiling it first. This adds some overhead to the execution time, especially for recursive functions that call themselves repeatedly.
  • Python does not have tail call optimization, which is a technique that eliminates the need for extra stack frames when a function returns the result of another function call. This means that Python has to allocate more memory and perform more operations for each recursive call, which can cause a stack overflow or a memory error for large values of n.
  • Python uses dynamic typing, which means that it does not check the type of the variables until runtime. This adds some overhead to the type checking and conversion process, which can slow down the arithmetic operations involved in the fibonacci sequence.

Mojo is faster than Rust on the fibonacci sequence, as you can see from the chart and the table. This is because Mojo has some advantages over Rust that make it more efficient and suitable for this task, such as:

  • Mojo has a zero-cost abstraction mechanism that enables the programmer to write high-level code without sacrificing performance or control over memory management. This means that Mojo can optimize the recursive function by eliminating unnecessary operations and memory allocations that Rust has to perform.
  • Mojo has a multi-level intermediate representation (MILR) that allows the programmer to manipulate the code at different levels of abstraction, from high-level Python-like syntax to low-level LLVM-like instructions. This means that Mojo can generate more optimized machine code than Rust, which has to rely on LLVM's optimization passes.
  • Mojo has a seamless integration with popular AI frameworks such as TensorFlow and PyTorch, as well as Modular's own AI hardware products. This means that Mojo can leverage the power of specialized hardware and software platforms that are designed for high-performance AI computation, while Rust has to use generic or third-party libraries and tools.


Conclusion


The performance difference you're seeing between Mojo and Rust in your Fibonacci sequence test could be due to several factors: Language Design, Compiler Optimizations, Code Structure, and Runtime Environment. Benchmarking programming languages can be complex and results can vary based on the specific task, code implementation, compiler used, and runtime environment.

Therefore, please don't judge the languages too quickly and let's figure out the performance step by step. You can also try to compare other aspects of the languages, such as their syntax, features, libraries, tools, and community support. You can also try to use different compilers or settings to see how they affect the performance. You can also try to write different versions of the Fibonacci function in each language, such as iterative, memoized, or matrix-based, and see how they compare. You can also try to use other benchmarks or tasks that are more relevant or realistic for your use case or interest.

I hope this benchmarking project was fun and educational for you. If you want to learn more about Python, Mojo, and Rust, you can visit their official websites or read their documentation . You can also try out their online playgrounds or download their IDEs . Happy coding! 😊

STATPAN

Post a Comment

Previous Post Next Post