לדלג לתוכן

7.5 איסוף זבל פתרון

מחיקה ידנית

class Enemy:
    def __init__(self, name: str):
        self.name = name

    def __del__(self):
        print(f"{self.name} נמחק מהזכרון")


e1 = Enemy("Goblin")
e2 = Enemy("Orc")
e3 = Enemy("Dragon")
e4 = Enemy("Witch")
e5 = Enemy("Troll")

print(f"נלחמים ב-{e1.name}")
del e1

print(f"נלחמים ב-{e2.name}")
del e2

del e3, e4, e5

מציאת דליפת זכרון

הבעיה: cache הוא רשימה גלובלית שגדלה ללא הגבלה - כל קריאה ל-process_user_request מוסיפה אליה רשומה ואף אחד לא מוחק.

תיקון אפשרי - הגבלת גודל הקאש:

from collections import deque

MAX_CACHE_SIZE = 100
cache = deque(maxlen=MAX_CACHE_SIZE)

def process_user_request(user_id: int, data: dict) -> dict:
    result = {"user_id": user_id, "processed": data}
    cache.append(result)
    return result

תיקון אחר - קאש לא גלובלי:

def process_user_request(user_id: int, data: dict) -> dict:
    return {"user_id": user_id, "processed": data}

אם אין צורך אמיתי בשמירת ההיסטוריה, פשוט מחזירים את התוצאה בלי לשמור אותה.

שאלות הבנה

1. זכרון לעומת אחסון:
- זכרון (RAM): מהיר מאוד, נמחק כשהמחשב נכבה, קטן יחסית. משמש לשמירת מידע שהתוכנה צריכה בזמן ריצה (משתנים, אובייקטים).
- אחסון (Storage/SSD/HDD): איטי, שומר מידע לצמיתות, גדול. משמש לקבצים שצריכים להישמר.

2. מתי GC לא מספיק:
כאשר אנחנו שומרים הפניה לאובייקטים שלא צריכים יותר בתוך מבנה נתונים (כמו רשימה גלובלית). הGC לא יכול למחוק אובייקטים שמישהו עדיין מצביע עליהם, גם אם שכחנו מהם.

3. מה קורה בלי שחרור זכרון:
התוכנה תצרוך יותר ויותר זכרון עם הזמן - תופעה הנקראת "memory leak". בסוף המחשב יאט, תוכניות אחרות יתחרו על הזכרון, ובמקרה קיצוני התוכנה תקרוס.