پایتون امروزه در زمینه های مختلف کاربرد دارد. از ماشین لرنینگ و پردازش تصویر گرفته تا بک اند و ساخت ربات تلگرام. یادگیری پایتون راحت است و به شما این قابلیت را میدهد تا مدل اولیه ایدهتان را در کمترین زمان لازم پیاده سازی کنید.
اما این زبان دوست داشتنی یک مشکل اساسی یعنی سرعت پایین دارد. برای حل این مشکل قصد داریم در این آموزش از زبان Rust کمک بگیریم و نتایج رو با قبل و بعد از استفاده از Rust بررسی کنیم.
کتابخانه های بزرگ و قدرتمندی مثل numpy, scipy, opencv و ... از زبانهای C و C++ برای حل مشکل سرعت پایتون استفاده میکنند. از آنجایی که زبان Rust قصد دارد خودش را با C و C++ جایگزین کند و حتی راه خودش را به کرنل لینوکس هم باز کرده، میتوان کتابخانههای پایتون را با زبان Rust هم ایجاد کرد. در ضمن Rust مشکلات مدیریت حافظه C یا C++ را تقریبا به طور کامل برطرف کرده است. در ادامه با من همراه باشید.
به تابعی نیاز داریم که یک رشته به عنوان ورودی دریافت کند و تعداد کاراکترهای 'a' موجود در رشته را شمرده و خروجی دهد.
ابتدا یک پروژه به اسم yasinlib به کمک cargo ایجاد میکنیم.
cargo new yasinlib cd yasinlib
فایل Cargo.toml را مطابق زیر بازنویسی میکنیم.
[package] name = "pyext-yasinlib" version = "0.1.0" authors = ["Yasin Arabi <yasinarabi@gmail.com>"] edition = "2021" [lib] name = "yasinlib" crate-type = ["dylib"] [dependencies.cpython] version = "0.7" features = ["extension-module"]
حال در فایل src/lib.rs تابع مدنظر را پیاده سازی میکنیم.
use cpython::{Python, PyResult, py_module_initializer, py_fn}; fn count_as(_py: Python, val: &str) -> PyResult<u64> { let mut counter = 0u64; for c in val.chars() { if c == 'a' { counter += 1; } } Ok(counter) } py_module_initializer!(yasinlib, |py, m | { m.add(py, "__doc__", "This module is implemented in Rust")?; m.add(py, "count_as", py_fn!(py, count_as(val: &str)))?; Ok(()) });
مطابق دستور زیر پروژه را build میکنیم.
cargo build --release
اگر با هیچ مشکلی مواجه نشویم باید در مسیر /target/release/ یک فایل به اسم libyasinlib.so داشته باشیم
اکنون فایل .so را در مسیر پروژه پایتون کپی میکنیم تا بتوانیم در فایل پایتون خود آن را import کنیم.
حال کد زیر را در فایل main.py مینویسیم.
در خط 6 یک رشته شامل یک میلیون کاراکتر تصادفی ایجاد میکنیم. تابعی که در خط 8 تا 13 نوشته ایم مشابه تابع کتابخانه Rust میباشد.
در خط 15 و 16 به ترتیب با استفاده از تابع timeit زمان 200 بار اجرای هر کدام از توابعی که در Rust و پایتون نوشتیم را اندازه گیری میکنیم و در خطوط 18 تا 20 نتایج را چاپ میکنیم.
همانطور که میبینید تابعی که در کتابخانه yasinlib وجود دارد بیش از 32 برابر سریعتر از پایتون عمل میکند.