عقوبة أداء الرسائل التي تمريرها بدلاً من البيانات المشتركة

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

سؤال

هناك الكثير من الطنانة هذه الأيام حول عدم استخدام الأقفال واستخدام أساليب تمرير الرسائل مثل Erlang. أو حول استخدام هياكل البيانات غير القابلة للتغيير مثل في البرمجة الوظيفية مقابل C ++/Java.

لكن ما يهمني هو ما يلي:

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

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

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

المحلول

  1. هذه هي الحياة الحقيقية : تحتاج إلى حساب هذا الاحتمال بغض النظر عن اللغة / النظام الأساسي. في عالم موزع (العالم الحقيقي) ، تفشل الأمور: العيش معه.

  2. بالطبع هناك تكلفة: لا شيء مجاني في عالمنا. ولكن ألا ينبغي أن تستخدم وسيطًا آخر (على سبيل المثال ، ملف DB) بدلاً من "الكائنات الكبيرة" المكوّنة في أنابيب الاتصال؟ يمكنك دائمًا استخدام "رسالة" للإشارة إلى "الكائنات الكبيرة" المخزنة في مكان ما.

  3. بالطبع لا: الفكرة وراء البرمجة الوظيفية / Erlang OTP هي "عزل"قدر الإمكان ، تم التلاعب بـ" الحالة المشتركة ". أماكن حيث يتم تحور الحالة المشتركة تساعد على اختبار وتتبع.

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

تذكر: تم تصميم إرلانج للمساعدة في حل منافس, غير متزامن و وزعت مشاكل. لم يتم تحسينه للعمل بكفاءة على كتلة مشتركة من الذاكرة على سبيل المثال ... ما لم تحسب التواصل مع nif وظائف تعمل على كتل مشتركة جزء من اللعبة :-)

نصائح أخرى

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

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

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

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

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

هناك بعض الافتراضات الضمنية في أسئلتك - أنت تفترض أن جميع البيانات يمكن أن تتناسب مع جهاز واحد وأن التطبيق مترجمة جوهريًا إلى مكان واحد.

ماذا يحدث إذا كان التطبيق كبيرًا جدًا ولا يمكن أن يتناسب مع جهاز واحد؟ ماذا يحدث إذا تفوق التطبيق على جهاز واحد؟

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

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

يجب ألا تتغير طريقة البرنامج فجأة لاستيعاب تسامح الأخطاء وقابلية التوسع.

تم تصميم Erlang في المقام الأول لبناء التطبيقات التي تتحمل الأخطاء.

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

يتم توزيع العديد من المشكلات بشكل جوهري ولا تتوفر البيانات أبدًا في مكان واحد في نفس الوقت - هذا النوع من المشكلات يتناسب بشكل جيد مع طريقة التفكير في إرلانج.

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

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

وتستخدم اللغات الأخرى

بعض التعليقات على سوء الفهم لديك عن إرلانج:

  • يضمن Erlang عدم فقد الرسائل ، وأن تصل إلى الطلب المرسل. يتمثل وضع الخطأ الأساسي في أن الجهاز A لا يمكن التحدث إلى الجهاز B. عندما يحدث ذلك ، ستشعر مراقبة العملية وسيتم تشغيل الروابط ، وسيتم إرسال رسائل عقدة النظام إلى العمليات المسجلة لها. لن يتم إسقاط أي شيء بصمت. ستقوم العمليات "بالتعطل" ويحاول المشرفون (إن وجد) إعادة تشغيلها.
  • لا يمكن تحور الكائنات ، لذلك يتم نسخها دائمًا. تتمثل إحدى طرق تأمين الثبات في نسخ القيم إلى أكوام عملية Erlang الأخرى. هناك طريقة أخرى تتمثل في تخصيص كائنات في كومة مشتركة ، وإشارات الرسائل إليها وببساطة لا تملك أي عمليات تحفرها. erlang يفعل الأول للأداء! يعاني الوقت الحقيقي إذا كنت بحاجة إلى إيقاف جميع العمليات إلى جمع القمامة جمع كومة مشتركة. اسأل جافا.
  • هناك حالة مشتركة في إرلانج. إرلانج ليس فخوراً به ، لكنه براغماتية حول هذا الموضوع. أحد الأمثلة على ذلك هو سجل العملية المحلي وهو خريطة عالمية تقوم بتخطيط اسم لعملية بحيث يمكن إعادة تشغيل عمليات النظام والمطالبة باسمها القديم. إرلانج فقط يحاول تجنب الحالة المشتركة إذا كان بإمكانها. جداول ETS التي هي عامة مثال آخر.
  • نعم ، أحيانًا يكون إرلانج بطيئًا جدًا. هذا يحدث جميع اللغات. في بعض الأحيان جافا بطيئة للغاية. في بعض الأحيان يكون C ++ بطيئًا جدًا. لمجرد أن حلقة ضيقة في لعبة ما كان عليها أن تنزل إلى التجميع لبدء بعض الرياضيات الخطيرة المستندة إلى SIMD ، لا يمكنك استنتاج أن كل شيء يجب أن يكتب في التجميع لأنها اللغة الوحيدة التي تكون سريعة عندما تكون مهمة. ما يهم هو القدرة على كتابة أنظمة لها أداء جيد ، ويدير Erlang جيدًا. انظر المعايير على Yaws أو RabbitMQ.

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

أولئك الذين لا يفهمون إرلانغ محكوم عليهم بإعادة تنفيذها بشدة.

حسنًا ، كان الأصل عن Lisp ، لكن ... هذا صحيح!

على سبيل المثال في ديسيبل ، يجب عليك الوصول إلى نفس السجل وتعديله

ولكن يتم التعامل مع هذا من قبل DB. كمستخدم لقاعدة البيانات ، يمكنك ببساطة تنفيذ استعلامك ، وتضمن قاعدة البيانات تنفيذها بمعزل عن غيرها.

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

تعتمد العديد من تحسينات البروتشر على عدم وجود آثار جانبية وحالة مشتركة أيضًا.

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

تنشأ العديد من المخاوف المشابهة لقضايا التزامن في الكود الفردي. وحدات المعالجة المركزية الحديثة هي أنابيب ، وتنفيذ التعليمات خارج الترتيب ، ويمكن تشغيل 3-4 منها في الدورة. لذلك حتى في برنامج واحد متخلف ، من الضروري أن يكون المترجم ووحدة المعالجة المركزية قادرين على تحديد الإرشادات التي يمكن تنفيذها وتنفيذها بالتوازي.

  1. يوفر Erlang المشرفين وعمليات اتصال Gen_Server للمكالمات المتزامنة ، لذلك ستعرف عنها إذا لم يتم تسليم رسالة: إما أن تُرجع مكالمة Gen_Server مهلة ، أو سيتم إسقاط العقدة بأكملها وأعلى إذا تم تشغيل المشرف.
  2. عادةً ما تكون العمليات على نفس العقدة ، تعمل لغات تمرير الرسائل على تحسين نسخ البيانات ، لذا فهي تشبه الذاكرة المشتركة تقريبًا ، إلا إذا تم تغيير الكائن المستخدم بعد ذلك ، والذي لا يمكن القيام به باستخدام الذاكرة المشتركة إما على أي حال
  3. هناك بعض الحالة التي يتم الاحتفاظ بها من خلال عمليات نقلها إلى أنفسهم في مكالم العودية ، كما يمكن أيضًا تمرير بعض الحالة عبر الرسائل. لا أستخدم Mnesia كثيرًا ، لكنها قاعدة بيانات للمعاملات ، لذلك بمجرد نقل العملية إلى Mnesia (وقد عادت) ، فأنت مضمون إلى حد كبير ستمر .. ستمر ..
  4. وهذا هو السبب في أنه من السهل ربط هذه التطبيقات في إرلانج باستخدام المنافذ أو برامج التشغيل. الأسهل هي المنافذ ، إنها تشبه إلى حد كبير أنبوب Unix ، على الرغم من أنني أعتقد أن الأداء ليس رائعًا ... وكما قيل ، فإن تمرير الرسائل ينتهي عادةً إلى أن يكون مؤشرًا يمر على أي حال حيث أن VM/برنامج التحويل البرمجي يحسن نسخة الذاكرة .

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

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top