Dart / التكامل: الأهداف والموارد والتحقق والأدلة / الدرس 13
فصل الحساب بحدود العوازل والرسائل
حلّل الذاكرة المعزولة والرسائل القابلة للنقل وIsolate.run وأعمار المنافذ وحدود التزامن الخاصة بالهدف.
في هذه الصفحة
أهداف الدرس
- ميّز تنفيذ العازل من الانتظار غير المتزامن داخل حلقة أحداث واحدة.
- صمّم عقود رسائل صغيرة وحدد مالكا لكل عامل ومنفذ ونتيجة وإخفاق.
العازل حد للذاكرة والتنفيذ
لعوازل Dart حالة قابلة للتغيير وحلقات أحداث منفصلة، ولا تشترك في رسم عادي من الكائنات القابلة للتغيير. تتواصل بآليات رسائل مدعومة. يمنع ذلك بعض تسابقات الذاكرة لكنه يضيف كلفة نسخ ونقل وتنسيق وأعمار. لا تنشئ async عازلا، ولا تجعل Futures كثيرة في عازل واحد حلقة حساب متوازية. استخدم عازلا آخر لفصل حساب مبرر على هدف يدعمه، لا كتحسين عام. للتزامن في المتصفح وسائل وقيود مختلفة؛ تتوجه أمثلة dart:isolate هنا إلى الآلة الافتراضية الأصلية، ولا يجوز وصفها ببرامج متوافقة مع المتصفح.
اشرح الحد بحساب واحد محدود
تنفذ Isolate.run الحساب المعطى في عازل جديد وتعيد Future لنتيجته. تتوفر الواجهة منذ Dart 2.19، وتستخدم الدورة خصائص لغة Dart 3 حيث يُذكر ذلك. يجمع المثال ثلاثة أعداد ثابتة، فتفوق كلفة الإنشاء العمل المفيد غالبا في تنفيذ حقيقي. يشرح ملكية النتيجة لا قياس أداء أو حجما موصى به للعامل. يجب أن يحقق الحساب وقيمته المعادة شروط النقل في الواجهة. لا توجد بيئة Dart أثناء التأليف، فلم يبدأ عازل أو عملية أو اختبار توقيت فعليا.
import 'dart:async';
import 'dart:isolate';
int sumValues(List<int> values) => values.fold(0, (total, value) => total + value);
Future<void> main() async {
final result = await Isolate.run(() => sumValues(<int>[1, 2, 3]));
print(result);
}
6
المخرج المتوقع 6 على آلة Dart افتراضية متوافقة تدعم الواجهة. المدخل ثابت وصغير، ولا يُدعى تسريع متواز أو قياس نقل ذاكرة أو نتيجة تنفيذ مرصودة.
أرسل بيانات بهوية وشكل صريحين
تعتمد قواعد الرسائل على واجهة العازل واشتراك العمال في الشيفرة. لا يمكن إرسال بعض الكائنات، وقد تحتفظ closure بحالة محيطة أوسع من المتوقع، منها مورد غير قابل للإرسال. فضّل حمولات صغيرة صريحة بدلا من كائن تطبيق يحوي ملفات أو منافذ أو عملاء أو حالة غير مرتبطة. يميّز بروتوكول العامل الطويل هوية الطلب والنجاح والرفض وفشل العامل. تحقق من الوارد قبل اعتباره حالة مجال موثوقة. يمنح تمرير SendPort قدرة اتصال؛ فوزعه وفق الملكية المطلوبة، ولا تفترض أن القناة تفرض كل تفويض التطبيق.
أغلق المنفذ عند انتهاء مالكه
تعرض ReceivePort تدفق رسائل واردة وsendPort للإرسال. هي مصدر اشتراك واحد وقد تخزن الرسائل حتى إرفاق مستمع. يرسل المثال رسالة إلى منفذ في العازل نفسه ثم يغلقه في finally. لا ينشئ عاملا عمدا؛ فالتسليم وإنشاء العامل آليتان منفصلتان. وللعامل الحقيقي حدّد الجاهزية والإيقاف ومراقبة الخطأ وإتمام الطلبات المعلقة. لا تثبت استجابة مطبوعة وحدها تحرير كل موارد العامل أو طلباته.
import 'dart:async';
import 'dart:isolate';
Future<void> main() async {
final port = ReceivePort();
try {
port.sendPort.send('ready');
print(await port.first);
} finally {
port.close();
}
}
ready
المخرج المتوقع ready على هدف أصلي داعم. هذه رسالة تعود داخل عازل واحد، لا دليل عامل ثان أو تواز في الحساب. لم يُنفّذ البرنامج.
حد إنشاء العمال وميّز الإلغاء من التخلي عن الانتظار
يحتاج تجمع العمال قبولا محدودا وخريطة نتائج وسلوكا واضحا عند توقف الطالب عن الانتظار. لا تنهي مهلة Future الحساب تلقائيا ولا تحسم أثرا خارجيا. وقد يهدر إنهاء العازل الصريح عملا؛ فحدّد ما يجوز التخلي عنه وكيف يعرف المعلق النتيجة. تجنب عازلا لكل عنصر صغير دون قياس النقل والبدء بمعيار معزول مخول. اذكر الهدف وSDK والحمل والمشاهدات عند توفرها. راجعت المادة المصدر ودلالات الواجهة فقط، ولم تختبر موثوقية عامل أو ضمان أداء.
الأخطاء الشائعة وإصلاحها
يُتوقع تنفيذ حلقة حساب async في عازل ثان.
- لماذا يحدث؟
- اختلطت صياغة النتيجة غير المتزامنة بالتنفيذ المعزول.
- كيف تصلحه؟
- اختر حد عازل صريحا مدعوما عندما يبرر فصل الحساب.
- كيف تتجنب تكراره؟
- حدّد عمل حلقة الأحداث وعمل العامل منفصلين.
تفشل رسالة عامل لأن كائنا ملتقطا غير قابل للإرسال.
- لماذا يحدث؟
- احتفظت closure بحالة محيطة أوسع من حاجة الحساب الظاهرة.
- كيف تصلحه؟
- مرّر مدخلا صغيرا قابلا للإرسال وافصل الحساب عن مالكي الموارد.
- كيف تتجنب تكراره؟
- راجع الملتقطات وقيود الرسائل قبل استخراج العامل.
يبقي منفذ أو عامل غير مستخدم عمل التطبيق حيا على غير المتوقع.
- لماذا يحدث؟
- لم تحدد ملكية إتمام العمر والإيقاف.
- كيف تصلحه؟
- أغلق المنافذ المملوكة وطبّق إيقاف العامل وسياسة الطلب المعلق.
- كيف تتجنب تكراره؟
- ضمّن الفشل والتخلي عن الانتظار في مراجعة العمر.
اختبر فهمك
1. هل يثبت إرسال رسالة عبر ReceivePort توازيا في الحساب؟
اعرض الحل المشروح
لا. يستطيع المنفذ الإرسال والاستقبال داخل العازل نفسه كما في المثال. يحتاج الحساب المتوازي حد تنفيذ مستقل مدعوما وعملا يسند إليه. وحتى حينها يلزم قياس الحمل وكلفة التنسيق لإثبات تسريع مفيد. لا تثبت صياغة الاتصال وحدها نتيجة أداء.
2. تصل نتيجة عامل دفعة بعد انتهاء مهلة المستدعي. ما الذي يجب أن يحسمه البروتوكول؟
اعرض الحل المشروح
حدّد هل تحفظ النتيجة للاستعلام اللاحق أو تتجاهل نتيجة حساب صرف آمنة أو تطابق عملية مؤثرة. أبق هوية الطلب وملكية الخطأ صريحتين وحد الحالة المحفوظة. لا تفسر المهلة دليلا لتوقف العامل أو لعدم وقوع فعل خارجي مثبت.
أهم ما تعلمته
- تتبادل العوازل الرسائل بدلا من مشاركة حالة معدلة عادية.
- يحتاج التنفيذ ونقل الرسائل ودعم الهدف وملكية العمر عقودا منفصلة.