實測相同程式碼用 Python 跟 Rust 寫出來的效能差異

將性能瓶頸的 Python 代碼用 Rust 重寫,編譯成 Python 可以直接調用的二進制模組。

Posted by Young on 2025-10-13
Estimated Reading Time 3 Minutes
Words 744 In Total

建立 Rust 專案

建立 Rust 資料夾

1
2
mkdir rust_corrector
cd rust_corrector

建立 Cargo.toml(Rust 的設定檔,類似 pyproject.toml

1
2
3
4
5
6
7
8
9
10
11
12
13
Cargo.toml 內容:
[package]
name = "rust_corrector"
version = "0.1.0"
edition = "2021"

[lib]
name = "rust_corrector"
crate-type = ["cdylib"] # ← 關鍵!編譯成動態庫供
Python 使用

[dependencies]
pyo3 = { version = "0.26", features =["extension-module"] } # ← PyO3 橋接

撰寫 Rust 程式碼

1
2
3
4
src/lib.rs 結構:
use pyo3::prelude::*; // ← 導入 PyO3

....

編譯指令

編譯成 Python 模組

1
uv run --no-project maturin develop --release
  1. 編譯 Rust 代碼 → 生成優化的機器碼
  2. 鏈接 Python C API → 透過 PyO3 橋接
  3. 生成 .so 檔案 → rust_corrector.cpython-313-darwin.so
  4. 安裝到虛擬環境 → .venv/lib/python3.13/site-packages/rust_corrector/

刪除 重新編譯

刪除已安裝的模組

1
uv pip uninstall rust_corrector -y

清理 Rust 編譯緩存(可選)

1
cd rust_corrector && cargo clean

重新編譯並安裝

1
uv run --no-project maturin develop --release

Python 調用 Rust 模組

就可以直接在 Python 中直接調用 Rust 編譯好的模組

1
import rust_corrector # ← 直接導入,就像普通 Python 模組
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌─────────────────────────────────────────────────┐
│ Python 程式 │
│ import rust_corrector │
│ rust_corrector.correct_text(...) │
└──────────────────┬──────────────────────────────┘
│ (Python C API)

┌─────────────────────────────────────────────────┐
│ PyO3 橋接層 │
│ - 型別轉換 │
│ - 錯誤處理 │
│ - GIL 管理 │
└──────────────────┬──────────────────────────────┘

┌─────────────────────────────────────────────────┐
│ Rust 編譯的機器碼 │
│ rust_corrector.so │
│ - correct_text() [native code] │
│ - pinyin 轉換 [native code] │
│ - edit_distance [native code] │
└─────────────────────────────────────────────────┘

為何 Rust 在 CPU 密集運算下會比 Python 快?

Rust 快的原因:

  1. ✅ 編譯成機器碼 - 更底層,無中間層
  2. ✅ 編譯器優化 - LLVM 做大量優化
  3. ✅ 無 GIL - 真正的多核並行
  4. ✅ 零成本抽象 - 高階語法,無性能損失
  5. ✅ 記憶體管理 - 編譯時確定,無 GC 開銷

Python 慢的原因:

  1. ❌ 解釋執行 - 每次都要翻譯
  2. ❌ 動態型別 - 運行時檢查型別
  3. ❌ GIL 限制 - 單核執行
  4. ❌ 記憶體開銷 - 動態分配 + 垃圾回收

靜態型別 vs 動態型別

  1. Rust:編譯期就知道所有變數型別,能幫助編譯器做最佳化。
  2. Python:每次運算(例如 a + b)都要檢查 a 和 b 的型別,甚至呼叫底層 C 函數,增加 overhead。

比如:

1
2
# Python 要判斷 int/float/str,甚至要拋錯
result = a + b

Rust 編譯期就知道 a 和 b 是什麼型別,直接生成對應的機器碼

1
2
// Rust 在編譯期就確定型別,CPU 直接執行加法
let result = a + b;

Python 的 GIL 問題

即使有 4 個 CPU 核心,同一時間只能有 1 個線程執行 Python 程式碼

Python:

Thread 1: 執行中 🟢
Thread 2: 等待 GIL 🔴
Thread 3: 等待 GIL 🔴
Thread 4: 等待 GIL 🔴

Rust 無 GIL: 可以真正利用多核 CPU

Thread 1: 執行中 🟢
Thread 2: 執行中 🟢
Thread 3: 執行中 🟢
Thread 4: 執行中 🟢

但 Python 的優勢是開發速度快! 所以我們用 Rust 重寫需要盡可能增加速度的部分,其他部分就保留 Python 👍

「Rust for speed, Python for productivity」

結論:Rust 靠「靜態型別 + 編譯最佳化 + 真正並行 + 記憶體安全」贏在效能;Python 靠「動態型別 + 解譯執行 + GIL」輸在速度,但贏在生態系和開發速度。兩者搭配常常是最好的解法。


若您覺得這篇文章對您有幫助,歡迎分享出去讓更多人看到⊂◉‿◉つ~


留言版