فرض کنید یکی از سرویسهای ساده و تکرارشونده، بهطور غیرمنتظرهای شروع به مصرف بیش از حد حافظه کند. کد تغییری نکرده ، لاگها خطایی نشان نمی دهند، و پردازشها همان روال همیشگی را طی میکنند. اما پس از حذف دادهها از map و حتی اجرای دستی GC، حافظه آزاد نمی شود، مصرف بالا ثابت مانده است.
بررسی کد
ساختار برنامه ساده بود: بارگذاری یک میلیون رکورد در حافظه، پردازش آنها، حذف دادهها و تکرار این چرخه. پیادهسازی با زبان Go انجام شده بود و map اصلی به شکل زیر تعریف شده بود
:
treasureChest := make(map[int][128]byte)
// پر کردن map
for i := 0; i < 1_000_000; i++ {
treasureChest[i] = [128]byte{}
}
// پردازش دادهها...
// پاکسازی map
for i := 0; i < 1_000_000; i++ {
delete(treasureChest, i)
}
runtime.GC() // اجرای دستی جمعآوری زباله
با وجود اجرای کامل delete روی کل map و همچنین فراخوانی مستقیم runtime.GC(), حافظه اشغالشده توسط برنامه بهطور محسوسی کاهش نیافت.
در Go، ساختار داخلی map بهگونهای طراحی شده که برای حفظ عملکرد، حافظهی اختصاصیافته به bucketها را حتی پس از حذف مقادیر، بلافاصله آزاد نمیکند. این یعنی حتی زمانیکه map منطقی خالی است، ساختار دادهای پشت آن همچنان بخش قابلتوجهی از حافظه را نگه میدارد. جمعآورنده زباله (GC) نیز بهدلیل باقیماندن رفرنسهای داخلی، این حافظه را آزاد نخواهد کرد — مگر در شرایط خاصی که بازسازی map یا اختصاص مجدد صورت گیرد.
برای ارزیابی رفتار متفاوت، همان سناریو در Rust با استفاده از HashMap پیادهسازی شد. پس از بارگذاری دادهها و استفاده از clear() برای حذف کامل محتوا، حافظه بلافاصله آزاد شد و مصرف به وضعیت اولیه بازگشت. در Rust، حافظه تحت مالکیت صریح دادههاست و زمانی که دادهها حذف میشوند، حافظهی مربوط به آنها نیز آزاد میشود؛ مگر اینکه عمداً نگهداری شود.
use std::collections::HashMap;
fn main() {
let mut treasure_chest: HashMap<u32, [u8; 128]> = HashMap::new();
for i in 0..1_000_000 {
treasure_chest.insert(i, [0u8; 128]);
}
// پردازش دادهها...
treasure_chest.clear(); // آزادسازی حافظه
}
گیریاین رفتار تفاوتی کلیدی میان زبانهای Go و Rust را نشان میدهد:
در Go، مدیریت حافظه بهشکلی پنهان و بهینهشده برای عملکرد طراحی شده، که در موارد خاص میتواند منجر به نگهداری ناخواسته حافظه شود. در مقابل، Rust با طراحی مالکیت و کنترل دقیقتر روی حافظه، امکان آزادسازی صریح و قابل پیشبینی را فراهم میکند.
، ز
بانهایی با مدل حافظه صریحتر مانند Rust انتخاب بهتری خواهند بود.Please open Telegram to view this post
VIEW IN TELEGRAM
Anophel
Anophel | Where Developers Create Their Own Path
Anophel is an ecosystem for developers—a place for those who prefer building over consuming. If you want to create tools, think differently, and forge your own path in coding, Anophel is with you.