Performance Comparison: Python vs Rust for Fibonacci Calculation
Performance Comparison: Python vs Rust for Fibonacci Calculation
When it comes to computational performance, choosing the right programming language can make a significant difference. This post explores a practical comparison between Python and Rust implementations of the Fibonacci sequence calculator, complete with instrumentation for precise performance measurements.
graph TD;
A[Start] --> B[End];
Project Structure
graph TD;
A[Project Root] --> B[Python Implementation];
A --> C[Rust Implementation];
A --> D[Profiling Script];
B --> E[fib2.py];
C --> F[fib2.rs];
D --> G[profiler.sh];
G --> H[performance_metrics.csv];
Performance Overview
gantt
title Performance Comparison: Python vs Rust (Fibonacci 40)
dateFormat X
axisFormat %s
section Python
7.47 seconds: 0, 7.47
section Rust
0.174 seconds: 0, 0.174
Code Implementation
Let's look at our baseline implementations. All code is available on Codeberg.
Python Implementation (fib2.py
)
import time
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
start_time = time.time()
fibonacci(40)
end_time = time.time()
execution_time = end_time - start_time
print(execution_time)
Rust Implementation (fib2.rs
)
use std::time::Instant;
fn fibonacci(n: u32) -> u32 {
match n {
0 => 0,
1 => 1,
_ => fibonacci(n - 1) + fibonacci(n - 2),
}
}
fn main() {
let start = Instant::now();
fibonacci(40);
let duration = start.elapsed();
println!("{:.4}", duration.as_secs_f64());
}
Profiling Script (profiler.sh
)
#!/bin/bash
# File to store performance metrics
output_file="performance_metrics.csv"
# Create the CSV file with headers if it doesn't exist
if [ ! -f "$output_file" ]; then
echo "Timestamp,Language,ExecutionTime" > "$output_file"
fi
# Number of iterations to run
iterations=10
# Function to run Python script and log execution time
run_python() {
start_time=$(date +%Y-%m-%dT%H:%M:%S.%3N)
execution_time=$(python3 fib2.py)
echo "$start_time,Python,$execution_time" >> "$output_file"
}
# Function to run Rust script and log execution time
run_rust() {
start_time=$(date +%Y-%m-%dT%H:%M:%S.%3N)
execution_time=$(./fib2)
echo "$start_time,Rust,$execution_time" >> "$output_file"
}
# Run Python and Rust scripts for specified iterations
for ((i=1; i<=$iterations; i++)); do
echo "Running iteration $i..."
run_python
run_rust
done
echo "Performance metrics saved to $output_file"
Results Analysis
graph TD;
subgraph Python[Python Execution Times]
A[Run 1: 7.29s] --> B[Run 2: 7.38s];
B --> C[Run 3: 7.34s];
C --> D[Run 4: 7.41s];
D --> E[Run 5: 7.33s];
end
subgraph Rust[Rust Execution Times]
F[Run 1: 0.174s] --> G[Run 2: 0.173s];
G --> H[Run 3: 0.174s];
H --> I[Run 4: 0.173s];
I --> J[Run 5: 0.175s];
end
Key Findings
graph LR;
A[Performance Results] --> B[Python ~7.47s];
A --> C[Rust ~0.174s];
B --> D[Standard Library];
C --> E[Optimized Binary];
D --> F[CPU Bound];
E --> G[43x Faster];
Performance Analysis Setup
The experiment uses a bash-based profiler to ensure consistent timing measurements across both languages. This centralized approach provides several benefits:
- Unified timestamp generation
- Consistent metrics collection
- Language-agnostic measurement system
- Data format suitable for further analysis
Implementation Details
Both implementations calculate the 40th Fibonacci number using recursive approaches. The profiler executes each implementation 10 times and records:
- Timestamp of execution
- Programming language used
- Execution duration in seconds
Raw performance data sample:
2024-12-30T06:11:39.250,Python,7.291918516159058
2024-12-30T06:11:46.559,Rust,0.1744
2024-12-30T06:11:46.736,Python,7.383427619934082
2024-12-30T06:11:54.137,Rust,0.1739
Optimization Opportunities
For Python:
- Replace recursion with dynamic programming
- Consider using PyPy for improved performance
- Implement memoization
- Explore Numba or Cython for critical sections
For Rust:
- Use release mode compilation (
cargo build --release
) - Consider using u64 for larger numbers
- Explore const generics for compile-time evaluation
- Implement iterative solution for better memory usage
Conclusion
This performance comparison demonstrates the significant advantages of Rust for computationally intensive tasks, while also highlighting the importance of proper instrumentation and measurement in performance analysis. Even with unoptimized recursive implementations, the performance difference is substantial.
Want expert ML/AI training? Visit paiml.com
For hands-on courses: DS500 Platform
Recommended Courses
Based on this article's content, here are some courses that might interest you:
-
AWS Advanced AI Engineering (1 week) Production LLM architecture patterns using Rust, AWS, and Bedrock.
-
Rust GUI Development for Linux (4 weeks) Learn to create native Linux GUI applications using Rust and popular frameworks like Iced, GTK, and EGUI. Build practical projects while mastering Rust GUI development fundamentals.
-
Python Essentials for MLOps (5 weeks) Learn essential Python programming skills required for modern Machine Learning Operations (MLOps). Master fundamentals through advanced concepts with hands-on practice in data science libraries and ML application development.
-
Deno TypeScript Development (2 weeks) Build secure, modern TypeScript applications with Deno runtime
-
Rust-Powered AWS Serverless (4 weeks) Learn to develop serverless applications on AWS using Rust and AWS Lambda. Master the fundamentals of serverless architecture while building practical applications and understanding performance optimizations.
Learn more at Pragmatic AI Labs