שיטות עבודה מומלצות להקלת איסוף האשפה ב- .Net

ב- Microsoft.Net, איסוף האשפה הוא מנגנון שאומץ על ידי Common Language Runtime (CLR) לניקוי המשאבים הנצרכים על ידי היישום שלך. כשאתה יוצר אובייקטים ב- .Net, הם מאוחסנים בערימה המנוהלת. אמנם אתה צריך ליצור אובייקטים, אך ברוב המקרים אינך צריך לדאוג לנקות את האובייקטים - זמן הריצה יעשה זאת עבורך.

עם זאת, עליך לאמץ שיטות עבודה מומלצות ביישום שלך כדי להקל על איסוף האשפה ולעזור לו לנקות את המשאבים מהר יותר. אף על פי ש- NET מיומנת להשיב לעצמים מנוהלים, עליכם לעקוב אחר הנחיות מסוימות בכדי להקל על איסוף האשפה כדי לשפר את ביצועי היישום שלכם. במאמר זה ברצוני להציג דיון על אופן הפעולה של איסוף האשפה ועל שיטות העבודה המומלצות ביותר בכדי להקל על איסוף האשפה ב- .Net.

מתי מתבצע איסוף אשפה?

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

דורות

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

בעת כתיבת קוד, עליך להקפיד על שיטות עבודה מומלצות מסוימות. כדוגמה, עליך ליצור אובייקטים בהיקף המקומי ככל האפשר כדי להקל על איסוף האשפה. אובייקטים שנוצרים בהיקף הגבוה יותר נמצאים בדרך כלל בזיכרון לתקופה ארוכה יותר. אתה יכול לנצל את פרופיל CLR כדי להבין את דפוסי ההקצאה של היישום שלך.

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

אם עליכם להתקשר GC.Collect()לשיטה, עליכם להתקשר GC.WaitForPendingFinalizers()לאחר השיחה כדי GC.Collect()לוודא כי שרשור ההפעלה הנוכחי ממתין עד שמסיימים את כל האובייקטים.

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

System.GC.Collect();

System.GC.WaitForPendingFinalizers();

System.GC.Collect();

עליכם לוודא כי אתם ממזערים את ההקצאות הנסתרות וכותבים את הקוד בצורה שתמנע סיכויי קידום אובייקטים קצרי טווח לדורות גבוהים יותר. אתה לא צריך להתייחס לחפצים קצרי טווח מאלה הארוכים, כדי למנוע קידום חפצים קצרי טווח לדורות גבוהים יותר.

כדאי גם להימנע מכתיבת גמרים לשיעורים. אם יש לך גמר מיושם בכיתה שלך, אובייקטים של מחלקות כאלה יהפכו לאובייקטים ארוכי טווח שכן זמן הריצה צריך לקדם את האובייקטים הניתנים לסיום לדורות מבוגרים. עליך להגדיר אובייקטים לאפס לפני שתבצע שיחה ארוכת טווח אם אין צורך באובייקטים כאלה על ידי היישום. אם אינך זקוק עוד לאובייקט סטטי או לאובייקטים אחרים ביישום שלך, עליך להגדיר אותו לאפס לפני ביצוע שיחה ארוכה. אתה לא צריך להגדיר משתנים מקומיים לאפסים מכיוון שהם אינם נחוצים; זמן הריצה יכול לקבוע איזה אובייקט מקומי אינו מופנה בקוד שלך או שלא נעשה בו שימוש נוסף, ולכן אינך צריך להגדיר אף משתנה מקומי לאפס במפורש.