تحسين أداء تطبيقات Rust: للمبتدئين

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا Rust سريع بالفعل، لكنه ليس الحد الأقصى

\n\n

تُعتبر Rust بحق واحدة من أكثر لغات البرمجة النظامية أداءً. بفضل التجريدات ذات التكلفة الصفرية (zero-cost abstractions) ونظام الملكية الصارم، يعمل الكود المكتوب بلغة Rust غالبًا بنفس سرعة الكود المكافئ بلغة C أو C++. ومع ذلك، حتى في Rust توجد "مزالق" قد تبطئ التطبيق، خاصة لدى المطورين المبتدئين.

\n\n

في هذه المقالة، سنستعرض المبادئ الأساسية والتقنيات العملية لتحسين أداء تطبيقات Rust. ستتعلم كيفية تنميط الكود، وتجنب التخصيصات غير الضرورية، والعمل بكفاءة مع المجموعات، واستخدام قوة المترجم. المادة موجهة للمبتدئين، لذا ستكون جميع الأمثلة بسيطة ومفهومة قدر الإمكان.

\n\n

هل أنت مستعد لجعل كود Rust الخاص بك أسرع؟ هيا بنا!

\n\n

1. التنميط: قم بالقياس أولاً، ثم قم بالتحسين

\n\n

قبل تحسين أي شيء، تحتاج إلى فهم ما الذي يسبب البطء. في Rust، توجد أدوات ممتازة لذلك.

\n\n

1.1. المعايير مع cargo bench

\n\n

الطريقة القياسية هي استخدام المعايير (benchmarks). تتيح لك قياس وقت تنفيذ دوال محددة.

\n\n
// في الملف benches/my_bench.rs\nuse criterion::{criterion_group, criterion_main, Criterion};\n\nfn fibonacci(n: u64) -> u64 {\n    match n {\n        0 => 1,\n        1 => 1,\n        n => fibonacci(n-1) + fibonacci(n-2),\n    }\n}\n\nfn bench_fib(c: &mut Criterion) {\n    c.bench_function("fib 20", |b| b.iter(|| fibonacci(20)));\n}\n\ncriterion_group!(benches, bench_fib);\ncriterion_main!(benches);\n
\n\n

للتشغيل، أضف إلى Cargo.toml:

\n
[dev-dependencies]\ncriterion = "0.5"\n\n[[bench]]\nname = "my_bench"\nharness = false
\n\n

ثم نفذ cargo bench. ستحصل على أرقام دقيقة: وقت التنفيذ، الانحراف المعياري، والمقارنة مع التشغيلات السابقة.

\n\n

1.2. تنميط وحدة المعالجة المركزية (CPU) والذاكرة

\n\n

للتحليل الأعمق، استخدم:

\n
    \n
  • perf (لينكس) — أداة تنميط على مستوى النواة.
  • \n
  • Valgrind — للبحث عن تسربات الذاكرة وتحليل ذاكرة التخزين المؤقت (cache).
  • \n
  • flamegraph — تصور "النقاط الساخنة" في الكود.
  • \n
\n\n

مثال على توليد flamegraph:

\n
cargo install flamegraph\ncargo flamegraph --bin my_app\n# افتح flamegraph.svg في المتصفح\n
\n\n

سيظهر لك flamegraph أي الدوال تستهلك أكبر قدر من الوقت. سيساعدك هذا على التركيز على الأمور الرئيسية.

\n\n

2. التعامل مع الذاكرة: تجنب التخصيصات غير الضرورية

\n\n

التخصيصات في الكومة (heap) هي أحد أكثر أسباب بطء الكود شيوعًا. تمنحك Rust تحكمًا كاملاً في الذاكرة، لكن المبتدئين غالبًا ما يفرطون في استخدام Box و Vec و String.

\n\n

2.1. استخدم المكدس (stack) بدلاً من الكومة (heap)

\n\n

كلما أمكن، قم بتخزين البيانات على المكدس. على سبيل المثال، بدلاً من Vec لمجموعة صغيرة ثابتة، استخدم مصفوفة:

\n\n
// بطيء: تخصيص في الكومة\nlet data: Vec<i32> = vec![1, 2, 3, 4, 5];\n\n// سريع: المكدس\nlet data: [i32; 5] = [1, 2, 3, 4, 5];\n
\n\n

2.2. التخصيص المسبق للذاكرة

\n\n

إذا كان حجم المجموعة معروفًا مسبقًا، استخدم with_capacity:

\n\n
// سيء: الكثير من عمليات إعادة التخصيص\nlet mut v = Vec::new();\nfor i in 0..1000 {\n    v.push(i);\n}\n\n// جيد: تخصيص واحد\nlet mut v = Vec::with_capacity(1000);\nfor i in 0..1000 {\n    v.push(i);\n}\n
\n\n

2.3. تجنب الاستنساخ (cloning)

\n\n

استنساخ السلاسل النصية والهياكل الكبيرة هي عملية مكلفة. استخدم الاقتراض (&str بدلاً من String):

\n\n
fn process(s: &str) { /* ... */ }\n\n// سيء: استنساخ\nlet s = String::from("hello");\nprocess(&s.clone());\n\n// جيد: اقتراض\nprocess(&s);\n
\n\n

3. استخدام z

المدونات

توصيات الكتب