تحسين أداء asyncio: تصميم فعّال للاستهلاك والمعالجة
عندما نتعامل مع تصميم نظام يعتمد على asyncio في Python، يصبح من المهم فهم كيفية إدارة وتنظيم العمليات بشكل فعّال. في الكود الذي قدمته، يتم استخدام asyncio.Protocol
لاستقبال البيانات من الخادم وتخزينها في asyncio.Queue
. الآن، نريد تصميم coroutine آخر مسؤول عن استهلاك البيانات من الطابور ومعالجتها.
أولاً، يمكنك استخدام asyncio.Task
لتشغيل الcoroutine الخاص بالاستهلاك. يمكنك إنشاء asyncio.Task
باستخدام loop.create_task
كما في المثال التالي:
-
حل مشاكل إدارة التبعيات في Maven05/04/2024
-
تحسين أداء استعلامات قواعد البيانات30/03/2024
-
تجارب اختبار Jest للواجهة الأمامية04/04/2024
pythonasync def consumer():
while True:
message = await q.get()
# قم بتنفيذ المعالجة الخاصة بالرسالة هنا
# ...
consumer_task = loop.create_task(consumer())
ثم، يمكنك تشغيل المهمة باستخدام loop.run_forever()
بدلاً من loop.run_until_complete
. هذا سيحافظ على تشغيل الاستهلاك بشكل دائم:
pythonloop.run_forever()
فيما يتعلق بالقلق بشأن انخفاض البيانات في الطابور، يمكنك استخدام asyncio.Queue.get_nowait()
بدلاً من asyncio.Queue.get()
للحصول على الرسائل دون الانتظار في حالة عدم وجود بيانات في الطابور. يمكنك فحص إذا ما كانت الرسالة فارغة للتحقق من وجود بيانات قبل تنفيذ أي عمليات:
pythonasync def consumer():
while True:
try:
message = q.get_nowait()
if message:
# قم بتنفيذ المعالجة الخاصة بالرسالة هنا
except asyncio.QueueEmpty:
await asyncio.sleep(1) # انتظر لفترة زمنية معينة إذا كانت الطابور فارغة
بالنسبة لتحسين الرمز وتجنب استخدام متغير عام للطابور، يمكنك تمرير الطابور كمعامل إلى الcoroutine بدلاً من استخدام متغير عام. هذا يجعل الرمز أكثر تنظيمًا وقابلية للاستخدام.
المزيد من المعلومات
بالطبع، دعونا نستمر في توسيع المعلومات حول تصميم وتنظيم الكود بشكل أفضل.
للبداية، يُفضل دائمًا استخدام asyncio.ensure_future
بدلاً من loop.create_task
لإطلاق المهام. هذا يجعل الرمز أكثر وضوحًا ويوفر قابلية التبديل بين تقنيات التشغيل في المستقبل.
pythonconsumer_task = asyncio.ensure_future(consumer())
فيما يتعلق بالقلق بشأن توقف الconsumer بسبب قلة البيانات في الطابور، يمكنك استخدام asyncio.sleep
للانتظار لفترة زمنية قبل استعادة المحاولة. هذا يسمح بالتحكم الفعّال في كيفية التعامل مع حالة الطابور الفارغة.
pythonasync def consumer():
while True:
try:
message = q.get_nowait()
if message:
# قم بتنفيذ المعالجة الخاصة بالرسالة هنا
except asyncio.QueueEmpty:
await asyncio.sleep(1) # انتظر لفترة زمنية معينة قبل المحاولة مرة أخرى
كما يمكن تحسين أداء الرمز من خلال استخدام asyncio.gather
لتشغيل المهام بشكل متزامن إذا كان هناك عدة مهام يمكن تنفيذها بشكل مستقل.
pythonasync def main():
# ... قم بتشغيل الاتصال والاستهلاك هنا
await asyncio.gather(consumer_task, other_task1(), other_task2())
loop.run_until_complete(main())
في النهاية، يُشدد على أهمية وضوح الرمز وقابليته للصيانة. تنظيم الكود بشكل جيد يجعل فهمه وتطويره أسهل للفريق ولأي مطور آخر قد يعمل على البرنامج في المستقبل.