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". בסוף המחשב יאט, תוכניות אחרות יתחרו על הזכרון, ובמקרה קיצוני התוכנה תקרוס.