本次測試的目的是評估不同程式語言在執行高運算密集型任務時的效能差異。具體任務是使用 for loop
計算從 1 加到 1 億所需的時間。
- 硬體:MacBook Pro M3
- 測試內容:使用純粹語言實現和語言擴展實現,對相同計算進行性能比較。
語言/方法 | 時間(毫秒) |
---|---|
Pure Python | 19300.196208 |
Pure Node.js | 13861.808334 |
Pure Rust | 503.900833 |
NAPI | 521.039000 |
PyO3 | 5445.831917 |
-
Pure Python
- Python 的執行時間顯著較長,約 19 秒。這是因為 Python 是解釋型語言,動態類型和 GIL(Global Interpreter Lock)的特性導致其無法高效地執行計算密集型任務。
-
Pure Node.js
- Node.js 的效能優於 Python,執行時間約 13.8 秒,得益於 V8 引擎的 JIT(Just-In-Time)編譯技術。JIT 能夠在運行時對代碼進行優化,提升執行效率。
-
Pure Rust
- Rust 表現最為優異,僅需 503 毫秒完成任務。作為一種編譯型語言,Rust 的性能接近原生機器碼,特別適合計算密集型場景。
-
NAPI
- 使用 NAPI(Node.js 原生插件接口)實現 Rust 與 Node.js 的結合,執行時間僅比純 Rust 稍慢(約 521 毫秒)。這展示了 NAPI 的高效性能,幾乎保留了 Rust 的執行效率。
-
PyO3
- PyO3 將 Rust 程式嵌入到 Python 中,執行時間約為 5.4 秒,比純 Python 快了 3 倍以上。但相較 NAPI,PyO3 的性能稍受 GIL 和 Python 內部機制的影響。
- 效能表現總結:Rust 具有絕對的性能優勢,其次是通過 NAPI 和 PyO3 的擴展方案,Pure Node.js 優於 Python,而 Python 在純計算任務中的效能相對較差。
- 應用建議:
- 計算密集型應用建議使用 Rust 或透過 NAPI/PyO3 將 Rust 整合至現有系統。
- 若需快速開發,可選擇 Node.js 或 Python,但應透過擴展庫如 NumPy 或 Cython 優化性能。
- 測試不同優化技術:使用 Cython 或 PyPy 測試 Python 的性能提升。
- 多執行緒與多進程:測試語言在多核處理器下的性能表現。
- 其他運算環境:比較不同硬體(如 Intel 與 AMD 處理器)的效能差異。
以下是本次測試中使用的程式碼:
Python 測試程式碼:
import time
def sum_large_numbers(n):
total = 0
for i in range(1, n+1):
total += i
return total
def main():
start = time.perf_counter() # 或 time.time()
print(sum_large_numbers(1_000_000_000))
total_time = time.perf_counter() - start # 總時間(秒)
print(f"{total_time * 1000:.6f}ms")
main()
Node.js 測試程式碼:
function sumLargeNumbers(n) {
let total = 0n; // 使用 BigInt 處理大數
for (let i = 1n; i <= n; i++) {
total += i;
}
return total;
}
function main() {
const start = process.hrtime(); // 開始計時
const result = sumLargeNumbers(1_000_000_000n);
const elapsed = process.hrtime(start); // 結束計時,取得 [seconds, nanoseconds]
const elapsedTimeInMs = elapsed[0] * 1000 + elapsed[1] / 1e6; // 轉換為毫秒
console.log(result.toString());
console.log(`${elapsedTimeInMs.toFixed(6)}ms`);
}
main();
Rust 測試程式碼:
use std::time::Instant;
fn sum_large_numbers(n: i64) -> i64 {
let mut total: i64 = 0;
for i in 1..=n {
total += i;
}
total
}
fn main() {
let start = Instant::now();
println!("{}", sum_large_numbers(1_000_000_000));
let total_time = start.elapsed();
println!("{:?}", total_time);
}