بناء عدة ملفات ثنائية في Rust: Cargo والأداء

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

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

ابدأ الدورة

كيفية بناء عدة ملفات ثنائية باستخدام Cargo دون فقدان الأداء؟

\n\n

هل سبق لك أن واجهت موقفًا حيث ينمو مشروع Rust الخاص بك إلى درجة لا يستطيع فيها ملف ثنائي واحد التعامل مع المهام؟ ربما تكتب أداة CLI يجب أن تحتوي على ملفات تنفيذية منفصلة لمهام مختلفة: واحد لتحليل البيانات، وآخر لتوليد التقارير، وثالث للتفاعل مع API. أو ربما تقوم بإنشاء تطبيق خادم حيث تحتاج إلى فصل المراقبة ومعالجة الطلبات والمهام الخلفية.

\n\n

السؤال "How can I build multiple binaries with Cargo?" هو أحد أكثر الأسئلة شيوعًا على Stack Overflow بين مطوري Rust. وهذا ليس من قبيل الصدفة. عندما يتجاوز المشروع حدود "Hello, World!" البسيطة، تصبح القدرة على تنظيم بناء عدة ملفات ثنائية بمهارة مهارة بالغة الأهمية. ولكن كيف تفعل ذلك دون فقدان الأداء؟ كيف لا تغرق في تكرار الكود ولا تبطئ عملية الترجمة؟

\n\n

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

\n\n

لماذا عدة ملفات ثنائية؟ مشكلة الملف التنفيذي الواحد

\n\n

تخيل: لقد كتبت مكتبة رائعة للعمل مع البيانات. ثم أضفت واجهة CLI. ثم خادم ويب. ثم جدولة مهام. كل ذلك في مشروع واحد. النتيجة؟ كتلة واحدة:

\n\n
    \n
  • تستغرق الترجمة وقتًا طويلاً، حتى لو قمت بتغيير سطر واحد فقط في CLI.
  • \n
  • تتطلب إعادة تشغيل التطبيق بأكمله عند تحديث مكون واحد.
  • \n
  • يصعب اختبارها ونشرها.
  • \n
\n\n

الحل هو تقسيم المشروع إلى عدة ملفات ثنائية. ولكن كيف تفعل ذلك بشكل صحيح في Rust؟

\n\n

الأساسيات: Cargo.toml وقسم [[bin]]

\n\n

أبسط طريقة هي الإعلان عن عدة أهداف ثنائية في ملف Cargo.toml الخاص بك. دعنا نستعرض مثالًا أساسيًا.

\n\n
// Cargo.toml\n[package]\nname = "my_project"\nversion = "0.1.0"\nedition = "2021"\n\n[[bin]]\nname = "analyzer"\npath = "src/bin/analyzer.rs"\n\n[[bin]]\nname = "reporter"\npath = "src/bin/reporter.rs"\n\n[[bin]]\nname = "server"\npath = "src/bin/server.rs"\n\n[dependencies]\nserde = { version = "1.0", features = ["derive"] }\ntokio = { version = "1", features = ["full"] }\n
\n\n

الآن في مجلد src/bin/ لديك ثلاثة ملفات: analyzer.rs و reporter.rs و server.rs. كل منها هو ملف ثنائي كامل مع دالة main() الخاصة به.

\n\n

لبناء كل شيء مرة واحدة:

\n
cargo build --release
\n\n

أو ملف ثنائي محدد:

\n
cargo build --release --bin analyzer
\n\n

بسيط؟ نعم. ولكن في هذا يكمن المأزق. إذا لم تقم بتحسين البناء، فسيتم ترجمة كل ملف ثنائي من جديد، حتى لو كانت تستخدم نفس التبعيات. وهذا طريق مباشر لفقدان الأداء.

\n\n

تحسين أداء البناء: ملفات تعريف Cargo

\n\n

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

\n\n

ملفات التعريف الأساسية: dev و release

\n\n

افتراضيًا، يستخدم Cargo ملفي تعريف: dev (للتطوير) و release (للإنتاج). ولكن يمكنك إنشاء ملفات التعريف الخاصة بك أو تعديل الملفات الموجودة.

\n\n
// Cargo.toml\n[profile.release]\nopt-level = 3          # أقصى تحسين للكود\nlto = "fat"            # تحسين وقت الربط (دمج جميع الكريتات)\ncodegen-units = 1      # وحدة واحدة لتوليد الكود لتحسين أفضل\nstrip = true           # إزالة معلومات التصحيح\n
\n\n

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

المدونات

توصيات الكتب