هو النوم () فكرة جيدة عن الحلقة الرئيسية لتطبيق جدولة الوظائف

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

سؤال

أنا أكتب تطبيقا جدولة وظيفة في Ruby لعملي (في المقام الأول لنقل الملفات باستخدام بروتوكول مختلف بتردد معين)

بلدي حلقة الرئيسية تبدو وكأنها هذه:

while true do
  # some code to launch the proper job
  sleep CONFIG["interval"]
end

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

هل هناك طريقة أخرى للقيام بنفس الشيء، أو هي sleep() آمنة بما فيه الكفاية في حالتي؟

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

المحلول

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

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

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

  1. الموقت الذي يستيقظ الخيط بشكل دوري للقيام بعمله.
  2. يحتاج الحدث الذي يتم تعيينه عندما يحتاج عملية إلى إلغاء أو تماما (تحكم المحاصرة-C على سبيل المثال).

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

نصائح أخرى

في أي وقت أشعر بالحاجة إلى منعه، استخدم حلقة حدث؛ عادة ليبيف. هنا ملزمة روبي:

http://rev.rubyforge.org/rdoc/

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

سيكون تدفق طلبك:

main {
   Timer->new( after => 0, every => 60 seconds, run => { <do your work> } )
   loop();
}

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

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

في حين sleep(timeout) مناسبة تماما لبعض التصاميم، هناك تحذير مهم في الاعتبار.

تثبيت روبي معالجات إشارة مع SA_RESTART (يرى هنا)، وهذا يعني أنك sleep (أو ما يعادلها select(nil, nil, nil, timeout)) لا يمكن إغلاقها بسهولة. سوف معالج إشارة الخاص بك النار، ولكن البرنامج سوف يذهب مباشرة إلى sleep. وبعد قد يكون هذا غير مريح إذا كنت ترغب في الرد في الوقت المناسب، على سبيل المثال SIGTERM.

اعتبر ذلك ...

#! /usr/bin/ruby
Signal.trap("USR1") { puts "Hey, wake up!" }
Process.fork() { sleep 2 and Process.kill("USR1", Process.ppid) }
sleep 30
puts "Zzz.  I enjoyed my nap."

... سوف يستغرق حوالي 30 ثانية لتنفيذ، بدلا من 2.

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

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

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