مشاكل قياس الوقت أو المدة - Monotonic Clock
1import time
2
3
4start_time = time.time()
5longProcess()
6end_time = time.time()
7
8
9if end_time - start_time < 5:
10 doSomething()هذا الكود بسيط جدا، وقد يعمل بشكل طبيعي لسنوات طويلة، لكنه قد يتعطل فجأة يوما ما ويسبب مشاكل كبيرة جدا!!
قياس الوقت والمدة مهم في كثير من الحالات فقد ينبني على نتيجة القياس عملية TimeOut أو Retry لبعض العمليات، او قد ينبني عليها Rate Limiting لبعض المستخدمين، أو إرسال Alerts للمراقبة.
المثال باستخدام Python، لكن الموضوع ينطبق على جميع لغات البرمجة.
كيف قد يتعطل هذا الكود مع أنه عمل لمدة طويلة بلا مشكلة؟؟
لو قفزت الساعة للأمام 10 ثوانٍ أثناء التنفيذ، سيبدو أن العملية استغرقت أكثر مما استغرقته فعلياً. أو لو رجعت للوراء، قد تكون النتيجة سالبة.
مشكلة قياس الوقت باستخدام time.time() هي اعتمادها على وقت نظام التشغيل. ووقت نظام التشغيل متغير، فقد يتم تعديله من Process أخرى سواء كتعديل يدوي، أو بسبب مزامنة مع سيرفر NTP
، والذي قد يقرر تغيير وقت نظام التشغيل بسبب عدم صحة الوقت الحالي، أو لتغيير التوقيت الصيفي والشتوي (Daylight Saving) أو لإضافة الـ Leap Seconds (ثواني ضائعة يتم إضافتها بسبب التغير في سرعة دوران الأرض).
دالة time.time() ترجع عدد الثواني التي مضت منذ وقت ثابت (يسمى Unix Epoch وهو 1970-01-01 00:00:00)، وهي تعتمد على توقيت نظام التشغيل.
الحل لقياس المدة دون التأثر بتغييرات ساعة نظام التشغيل، هو استخدام ساعة غير مرتبطة بـ Unix Epoch ولا ينطبق عليها تغييرات الـ Leap Seconds ولا تحتاج إلى ما يحتاجه البشر من تغيير للتوقيت، وهذا ما يسمى بالـ Monotonic Clock.
الـ Monotonic Clock تستخدم ضمن الجهاز الواحد فقط، في حال وجود أكثر من جهاز كمبيوتر، فقيمة الـ Monotonic Clock في الجهاز الأول لن تساوي قيمة الـ Monotonic Clock في الجهاز الثاني، لذلك مبحث قياس الوقت وتسلسل الأحداث مهم جدا في الـ Distributed Systems.
في بايثون، يمكنك استخدام time.monotonic() لمثل هذه الحالات، وفي كل لغة برمجة توجد Function مشابهة يمكنك استخدامها لمثل هذه الأغراض.
نفس المثال سيكتب بالطريقة التالية:
1import time
2
3
4start_time = time.monotonic()
5longProcess()
6end_time = time.monotonic()
7
8
9if end_time - start_time < 5:
10 doSomething()