محتويات الدورة

بايثون / أنظمة قابلة للصيانة / الدرس 17

التنميط وكلفة الخوارزمية والذاكرة

قس عملا ممثلا، وميز الزمن عن الذاكرة المحتفظ بها، وحسن الكلفة الغالبة دون تغيير العقد السلوكي.

وقت القراءة التقريبي: 4 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • ابدأ بسؤال وخط أساس
  • تحديد المخازن المؤقتة والتحقق من المكاسب

ابدأ بسؤال وخط أساس

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

فصل القياس الزمني عن إسناد الكلفة

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

تغيير الخوارزمية أهم من تجميلها

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

python تغيير الخوارزمية أهم من تجميلها — مثال محلول
import cProfile
import pstats

def sum_squares(values):
    return sum(value * value for value in values)

profiler = cProfile.Profile()
result = profiler.runcall(sum_squares, range(5))
stats = pstats.Stats(profiler)
called = any(key[2] == "sum_squares" for key in stats.stats)
print(result)
print(called)
الناتج المتوقع
30
True

النتيجة القابلة للفحص 0 + 1 + 4 + 9 + 16. يحوي التنميط الدالة المستهدفة، أما الزمن الفعلي فيخص البيئة.

تتبع التخصيص لا كل الذاكرة

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

python تتبع التخصيص لا كل الذاكرة — مثال محلول
import tracemalloc

tracemalloc.start()
payload = bytearray(100_000)
current, peak = tracemalloc.get_traced_memory()
print(current >= len(payload))
print(peak >= current)
tracemalloc.stop()
الناتج المتوقع
True
True

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

تحديد المخازن المؤقتة والتحقق من المكاسب

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

الأخطاء الشائعة وإصلاحها

تغيير معالجة التكرار بعد التحسين

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

ظهور getsizeof أصغر بكثير من ذاكرة العملية

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

نمو المخزن المؤقت بلا نهاية

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

اختبر فهمك

1. يكشف التنميط مساعدا رخيصا استدعي مليون مرة. ماذا تفحص؟

اعرض الحل المشروح

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

2. كيف تميز ذروة مؤقتة من نمو باق؟

اعرض الحل المشروح

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

أهم ما تعلمته

  • قس المقياس والحمل المهمين.
  • احفظ السلوك عند تغيير الخوارزميات.
  • ميز التخصيص والذروة والباقي وذاكرة العملية.

المراجع الرسمية