304. string Intern

[נכתב ע”י שני אלחרר]

אהלן.

הטיפ היומי הוא על תכולה נפלאה בCLR שעוזרת לנו לחסוך בזיכרון ובזמני ריצה – “String Interning”.

לCLR של .Net יש Pool של stringים שאנחנו יכולים להשתמש בו, ולרוב משתמשים בו (כשאנחנו משתמשים בstring שידוע בזמן קימפול). והוא עוזר לנו לחסוך זיכרון ואפילו לקצר את זמני הריצה באופן ישיר.

איך הוא עוזר לנו לחסוך זיכרון ?

אם אני אעשה את הפעולה הבאה :

1
2
3
string a = "a" + 1;
string b = "a" + 1;
Console.Out.WriteLine(ReferenceEquals(a, b));

אקבל בפלט את הערך false, זה אומר שאני מחזיק את המחרוזת "a1" פעמים בזיכרון.

אם אריץ את הפקודה הבאה :

1
2
3
string a = "a";
string b = "a";
Console.Out.WriteLine(ReferenceEquals(a, b));

אקבל את הערך True, זאת מכיוון שאנחנו מקבלים את הStringים אוטומטית מהPool כאשר אנחנו עושים השמה של stringים שהם קבועים בזמן קמפול.

כלומר, איני צריך לבקש מהCLR את הstring מהPool אם אני שם ערך שהוא קבוע בזמן קימפול, אבל אם יש לי string שנבנה באופן דינאמי, אוכל לבקש את הערך שלו כך :

1
2
3
string a = string.Intern("a" + 1);
string b = string.Intern("a" + 1);
Console.Out.WriteLine(ReferenceEquals(a, b));

ולכן גם במקרה הזה אקבל את הערך true, כמובן שבמקום הביטוי "a" + 1 אוכל להכניס כל ביטוי שנבנה בזמן ריצה.

נוכל לחסוך כך זיכרון בכך שיש לי ייצוג של כל string אך ורק פעם אחת בזיכרון, ובזמן ריצה בכך שאם אני משווה stringים, אז השוואת ה-ReferenceEquals (שמתבצעת ראשונה) תחזיר true – וזוהי ההשוואה המהירה ביותר, ולכן אנחנו בודקים Referenceים לפני שאנחנו בודקים השוואה של תו לתו בין המחרוזות.

במקרה שאנחנו יוצרים Stringים דינאמית כדי לכתוב לLog או לConsole, ואנחנו מבינים שלא נצטרך לעשות איתו הרבה פעולות – אין צורך לבצע string.Intern על המחרוזת, כי זה יקח יותר זמן לחפש אותו בPool מאשר להשתמש ולזרוק את המחרוזת.

בברכת יום ירוק וממוחזר.

שתף