Ninja: خيار لاستخدام خصائص الملف بدلاً من الطوابع الزمنية

تم إنشاؤها على ١٤ أغسطس ٢٠١٨  ·  15تعليقات  ·  مصدر: ninja-build/ninja

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

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

أنا أفهم أن استخدام تجزئات الملفات أو غيرها من خصائص الملفات الجوهرية يمكن أن تبطئ Ninja لذا يجب أن يكون استخدامها خيارًا.

feature

التعليق الأكثر فائدة

لقد استخدمت أيضًا التجزئة في العمل ، بنجاح كبير. يعتمد على # 929 ، ولكن مع مجموعة من التصحيحات ، كما يمكن رؤيته في https://github.com/moroten/ninja/commits/hashed. hash_input = 1 على القواعد المختارة ملائم للغاية. لا يزال الفرع الخاص بي يحتوي على خطأ حيث تكون الملفات stat غالبًا ، O(n^2) بدلاً من O(n) . الخطأ مرتبط بالحواف الزائفة.

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

هناك فكرة أخرى تتمثل في جعل عنصر التجزئة من الدرجة الأولى في النينجا ، أي نقل التجزئة إلى سجل الإنشاء. قد يكون استخدام SHA256 خطوة واحدة نحو إضافة دعم لواجهة برمجة تطبيقات التنفيذ عن بُعد الخاصة بـ Bazel. يمكن العثور على تطبيق C ++ على https://gitlab.com/bloomberg/recc/. ألن يكون هذا لطيفًا جدًا؟

لسوء الحظ ، من المحتمل أن يؤدي فرز دلالات الحواف الزائفة إلى كسر التوافق مع الإصدارات السابقة.

ال 15 كومينتر

929 لديه تنفيذ. على الرغم من استخدامه بنجاح (في مفترق) لآلاف الإصدارات يوميًا ، إلا أنه لم يتم اعتباره للدمج.

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

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

الاستجابة للوسيطة ذات الخيط الفردي: نعم ، إنها تضيف إرشادات إلى حلقة الخيط المفرد. في الواقع ، هذا مهم فقط إذا كان الخيط الفردي يحصل على عمل أكثر مما يمكن أن ينجح (على سبيل المثال ، تنتهي قواعد أكثر مما يمكن أن يعالجها مؤشر ترابط واحد (depslog + hashlog + ...)). عندها فقط يؤلم التجزئة. وإلا فإن حلقة الخيط المفرد تنتظر انتهاء المهام على أي حال. لم نشاهد مطلقًا نينجا مشغولًا بالتجزئة حتى مع تجربة -j1000. (وبالنسبة لقواعد الإنهاء السريع ، فإن التجزئة على أي حال ليست مثيرة للاهتمام في الوقت الآمن.)

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

أخيرًا ، التنفيذ في # 929 هو الاشتراك ولا يأتي بدون تكلفة للأشخاص الذين لا يستخدمون الميزة (إلى جانب عبارة if).

التجزئة ، على سبيل المثال ، جميع مدخلات قواعد الارتباط باهظة الثمن وبالتالي فهي غير مرغوبة ، في حين أن الملفات المصدر وتبعياتها المعروفة هي مرشحة جيدة.

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

إذا كان الأمر بطيئًا جدًا (على سبيل المثال مع المكتبات الثابتة الكبيرة) ، فيمكننا التفكير في تنفيذ التجزئة فقط للمدخلات النقية وليس للملفات الوسيطة. سيؤدي ذلك إلى حل حالة "تبديل فروع Git يؤدي إلى إعادة بناء كاملة" على الأقل.

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

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

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

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

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

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

لقد استخدمت أيضًا التجزئة في العمل ، بنجاح كبير. يعتمد على # 929 ، ولكن مع مجموعة من التصحيحات ، كما يمكن رؤيته في https://github.com/moroten/ninja/commits/hashed. hash_input = 1 على القواعد المختارة ملائم للغاية. لا يزال الفرع الخاص بي يحتوي على خطأ حيث تكون الملفات stat غالبًا ، O(n^2) بدلاً من O(n) . الخطأ مرتبط بالحواف الزائفة.

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

هناك فكرة أخرى تتمثل في جعل عنصر التجزئة من الدرجة الأولى في النينجا ، أي نقل التجزئة إلى سجل الإنشاء. قد يكون استخدام SHA256 خطوة واحدة نحو إضافة دعم لواجهة برمجة تطبيقات التنفيذ عن بُعد الخاصة بـ Bazel. يمكن العثور على تطبيق C ++ على https://gitlab.com/bloomberg/recc/. ألن يكون هذا لطيفًا جدًا؟

لسوء الحظ ، من المحتمل أن يؤدي فرز دلالات الحواف الزائفة إلى كسر التوافق مع الإصدارات السابقة.

في غضون ذلك ، أعددت حلاً لحالة استخدامي لتبديل الفروع في Chromium (وهو أمر مؤلم بشكل خاص) ؛ برنامج Go الصغير والنص البرمجي الذي أستخدمه موجودان هنا: https://github.com/bromite/mtool

لا تتردد في تكييفه مع حالات الاستخدام الخاصة بك ، إذا كان يعمل مع Chromium ، فأنا أراهن أنه سيعمل أيضًا مع مشاريع الإنشاء الأصغر (وسيستغرق وقتًا ضئيلًا لإجراء عمليات التشغيل الخاصة بي). الجانب السلبي الوحيد هو أنك إذا استخدمت البرنامج النصي الذي قمت بنشره هناك كما هو ، فسيتم التخلص من ملفات .mtool في كل مكان في كل دليل أصل في مستودع git ، ولكن لا شيء لا يمكن لـ gitignore عالمي علاجه.

من المثير للاهتمام ملاحظة أنني أستخدم الناتج git ls-files --stage لاحتياجات التجزئة ؛ من الممكن (ولكن أقل كفاءة) أن تطلب git إلى تجزئة الملفات غير المفهرسة أيضًا إذا كان البناء الخاص بك يعتمد عليها.

يتوقع المرء من ناحية الميزة أن تنفيذ الميزة التي تتم مناقشتها هنا يمكن أن يفعل النينجا الشيء نفسه داخليًا (دون الاعتماد على git) وبنتائج أداء مماثلة.

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

سطر الأوامر مجزأ بالفعل من قبل النينجا وتخزينه في سجل البناء.

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

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

أعتقد أن Ninja يفترض بالفعل ويتخطى كل الأعمال عندما تتطابق الطوابع الزمنية. لذلك في مثالك سيكون هذا بناء غير صحيح على أي حال.

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

IMHO ، تخطي فحص التجزئة عندما تكون مطابقة الطوابع الزمنية تحسينًا صالحًا للغاية.

فحص التجزئة سوف يتجنب ببساطة بعض عمليات إعادة البناء "الخاطئة القذرة" ، مع الحفاظ على الدلالات الموجودة التي قدمها النينجا بالفعل.

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

rulatir أعتقد أنني أفهم غالبًا ما تقوله :) أعتقد أن هذا هو أحد الأسباب التي تجعل Bazel وأنظمة الإنشاء الأخرى القائمة على عمليات التحقق من التجزئة ضد المخرجات المستهدفة داخل الشجرة.

على الرغم من ذلك ، ألن يتم حل هذه المشكلة إذا كان نظام البناء سيتحقق مما إذا كانت الأهداف أحدث من الوقت المعروف سابقًا ، وإعادة البناء إذا لزم الأمر؟

rulatir أعتقد أنني أفهم غالبًا ما تقوله :) أعتقد أن هذا هو أحد الأسباب التي تجعل Bazel وأنظمة الإنشاء الأخرى القائمة على عمليات التحقق من التجزئة ضد المخرجات المستهدفة داخل الشجرة.

كيف تعتمد التجزئة على مكان الملف؟

على الرغم من ذلك ، ألن يتم حل هذه المشكلة إذا كان نظام البناء سيتحقق مما إذا كانت الأهداف أحدث من الوقت المعروف سابقًا ، وإعادة البناء إذا لزم الأمر؟

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

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات