ما هي أمثلة في العالم الحقيقي لرسم الرسم البياني التبعية في الخرج؟

StackOverflow https://stackoverflow.com/questions/2414281

  •  19-09-2019
  •  | 
  •  

سؤال

كما لاحظ في وثائق, ، يستخدم Gradle رسم بياني Acyclic موجه (DAG) لبناء رسم بياني للاعتماد. من فهمي، فإن وجود دورات منفصلة للتقييم والتنفيذ هو ميزة رئيسية لأداة البناء. على سبيل المثال متدرج دوك تنص على أن هذا يتيح بعض الميزات التي من شأنها أن تكون مستحيلة.

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

أقدم هذا "Wiki المجتمع" منذ البداية، حيث سيكون من الصعب تقييم الإجابة "الصحيحة".

هل كانت مفيدة؟

المحلول

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

سؤالي الأول هو السبب في أن الرسم البياني التبعي بمهام الخرج مضمون ليكون Acyclic. لم أجد الإجابة على ذلك، ولكن يتم بسهولة إنشاء حالة عكسية بسهولة، لذلك سأفترض أن اكتشاف الدورة هو التحقق من الصحة يتم تشغيله عند بنائه الرسم البياني، وفشل Build قبل تنفيذ المهمة الأولى إذا هناك تبعيات دورية غير قانونية. دون بناء الرسم البياني أولا، قد لا يتم اكتشاف حالة الفشل حتى يتم إكمال البناء تقريبا. بالإضافة إلى ذلك، سيتعين على روتين الكشف عن تشغيله بعد تنفيذ كل مهمة، والتي ستكون غير فعالة للغاية (طالما أن الرسم البياني قد تم بناؤه تدريجيا ومتوفر على المستوى العالمي، فسيكون البحث الأول من البحث فقط للعثور على نقطة انطلاق، ويلجأ ستحتاج تقييمات الدورة إلى الحد الأدنى من العمل، لكن العمل الكلي ستظل أكبر من القيام بتخفيض واحد على مجموعة العلاقات بأكملها في البداية). أنا الطباشير في الكشف المبكر فائدة رئيسية.

يمكن أن يكون التبعية المهمة كسولا (انظر: 4.3 تبعيات المهمة، مثال مقدم من 13.14). تعذر تقييم تبعيات المهمة الكسولة بشكل صحيح حتى يتم بناء الرسم البياني بأكمله. وينطبق الشيء نفسه على قرار التبعية المتعتقدين (غير المهمة)، مما قد يسبب مشاكل لا حصر لها، وتتطلب إعادة تحديثات متكررة حيث يتم اكتشاف تبعيات إضافية وحلها (تتطلب أيضا طلبات متكررة إلى مستودع). ميزة قواعد المهام (13.8) لن تكون ممكنة أيضا. هذه المشكلات، وهي على الأرجح العديد من الآخرين، يمكن تعميمها من خلال النظر في أن الخرج يستخدم لغة ديناميكية، ويمكن أن تضيف وتعديله ديناميكيا وتعديل المهام، لذلك قبل تقييم أول تمرير، يمكن أن تكون النتائج غير حتمية لأن مسار التنفيذ بنيت و تم تعديلها أثناء وقت التشغيل، وبالتالي، يمكن أن تنتج تسلسلات التقييم المختلفة نتائج مختلفة بشكل تعسفي إذا كانت هناك تبعيات أو توجيهات سلوكية غير معروفة حتى وقت لاحق، لأنها لم يتم إنشاؤها بعد. (قد يكون هذا يستحق التحقيق مع بعض الأمثلة الملموسة. إذا كان هذا صحيحا، فإن حتى مرورين لن يكونوا دائما كافية دائما. إذا أ -> ب، ب -> C، حيث يغير C سلوك بحيث لم يعد يعتمد على B، ثم لديك مشكلة. آمل أن يكون هناك بعض أفضل الممارسات حول تقييد المخططات التقوية مع النطاق غير المحلي، وعدم السماح لها في مهام تعسفية. مثال مرح سيكون محاكاة لمراقبة السفر وقت، حيث حفيد يقتل جده أو يتزوج جدته، ويوضح بوضوح بعض المبادئ الأخلاقية العملية!)

يمكن أن تمكن حالة أفضل وإعداد التقارير المرحلية بشأن بناء تنفيذ حاليا. يوفر TASKExecutionClistener قبل / بعد السنانير لمعالجة كل مهمة، ولكن دون معرفة عدد المهام المتبقية، لا يوجد الكثير يمكن أن يقول عن الوضع غير "6 المهام المكتملة. على وشك تنفيذ المهام فو." بدلا من ذلك، يمكنك تهيئة TaskexectionClistener مع عدد المهام في Gradle.taskgraph.whenready، ثم إرفاقه إلى TaskexecutionGraph. الآن يمكن أن توفر معلومات لتمكين تفاصيل التقرير مثل "6 من 72 مهام مكتملة. الآن تنفيذ المهمة فو. الوقت المقدر المتبقي: 2H 38M." من شأنه أن يكون من المفيد عرضه على وحدة تحكم لخادم التكامل المستمر، أو إذا كان الخرج يستخدم لتزويد التقديرات الكبيرة متعددة المشروعات وتقديرات الوقت حاسمة.

على النحو المشار إليه من قبل جيري بولارد، فإن جزء تقييم من دورة الحياة أمر بالغ الأهمية لتحديد خطة التنفيذ، والتي توفر معلومات حول البيئة، نظرا لأن البيئة تحدد جزئيا من خلال سياق التنفيذ (مثال 4.15 في التكوين بواسطة قسم DAG). بالإضافة إلى ذلك، أستطيع أن أرى أن هذا مفيد لتحسين التنفيذ. يمكن أن يتم تسليم المساءات المستقلة بأمان إلى مؤشرات ترابط مختلفة. يمكن أن تكون خوارزميات المشي للتنفيذ أقل كثافة في الذاكرة إذا لم تكن ساذجة (تقول حدستي إن المشي دائما في المسار مع معظم المساءات التي ستؤدي إلى مكدس أكبر من المسارات التي تفضيلها دائما مع الأقل المساءات).

قد يكون استخداما مثيرا للاهتمام لهذا الموقف حيث يتم حدوث العديد من مكونات النظام في البداية لدعم العروض التوضيحية والتطوير التدريجي. ثم أثناء التطوير، بدلا من تحديث تكوين البناء نظرا لأن كل مكون يصبح ينفذ، يمكن أن يحدد الإنشاء نفسه إذا كان برنامج فرعي جاهز للإدماج حتى الآن (ربما يحاول الاستيلاء على التعليمات البرمجية، وتجميعها، وتشغيل مجموعة اختبار محددة مسبقا) وبعد إذا كان الأمر كذلك، فإن مرحلة التقييم ستتكشف ذلك، وسيتم إدراج المهام المناسبة، وإلا فإنها تختار مهام الروبين. ربما هناك اعتماد على قاعدة بيانات Oracle غير متوفرة بعد، وأنت تستخدم قاعدة بيانات مضمنة في هذه الأثناء. يمكنك السماح للبناء بفحص التوفر، والتبديل بشفافية عندما يمكن، وإخبارك أنه تبحر قواعد البيانات، بدلا من إخباره بذلك. يمكن أن يكون هناك الكثير من الاستخدامات الإبداعية على طول تلك الخطوط.

المتدرج يبدو رائعا. شكرا لإثارة بعض الأبحاث!

نصائح أخرى

أ مثال من نفس الوثائق يوضح قوة هذا النهج:

نظرا لأننا نصف بالتفصيل الكامل لاحقا (انظر الفصل 30، فإن Meduckycle Build LifeCycle) لديه مرحلة التكوين ومرحلة التنفيذ. بعد معرفة مرحلة التكوين يعرف جميع المهام التي يجب تنفيذها. يقدم لك Madle هوك للاستفادة من هذه المعلومات. سيكون لحالة الاستخدام لهذا هو التحقق مما إذا كانت مهمة الإفراج جزءا من المهام المراد تنفيذها. اعتمادا على ذلك، يمكنك تعيين قيم مختلفة لبعض المتغيرات.

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

أقوم بتقييم أنظمة البناء المختلفة الآن ومع التقداري الذي تمكنت من إضافة رمز قبيح يطيع جميع مهام نوع "جرة" وتغييرها لذلك، فإن كل مظهر جرة يتضمن سمة "رقم البناء" (الذي يستخدم في وقت لاحق لإنشاء نهائي أسماء الملفات):

gradle.taskGraph.whenReady {
    taskGraph ->
    taskGraph.getAllTasks().findAll {
        it instanceof org.gradle.api.tasks.bundling.Jar
    }.each {
        it.getManifest().getAttributes().put('Build-Number', project.buildVersion.buildNumber)
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top