
اگر با Go کار کرده باشید، میدانید که گاربیجکالکتور (GC) آن همیشه یکی از نقاط قوتش بوده: کمتوقف، موازی و نسبتاً سریع. اما گوگل تازه یک زنگ خطر جدی زده: ۸۵٪ وقت GC صرف حلقهی اصلی اسکن حافظه میشود و بیش از ۳۵٪ از سیپییو فقط منتظر میماند تا داده از حافظه برسد.
مشکل این است که الگوریتم فعلی Go (سهرنگی موازی) مثل یک سیل، همهی اشیاء حافظه را بدون توجه به چیدمان فیزیکی آنها میگردد. نتیجه؟ کش پردازنده بیفایده، رفت و برگشتهای بیهوده به رم، و مصرف انرژی بالا.
با زیاد شدن هستههای پردازنده و کندتر شدن رم نسبت به سیپییو، این قضیه دارد تبدیل به یک بحران میشود.
تیم Go یک الگوریتم جدید طراحی کرده به اسم Green Tea. ایدهاش ساده است اما باهوشانه:
به جای اینکه تکتک اشیاء را در صف بریزیم، «بلوکهای پیوستهی ۸ کیلوبایتی» (که در Go به آنها Span میگویند) را در صف قرار میدهیم.
فرض کنید ۱۰ شیء کوچک کنار هم در یک بلوک ۸ کیلوبایتی هستند. در روش قدیم، این ۱۰ شیء بهصورت جداگانه وارد صف میشدند و هرکجا که بودند اسکن میگشتند. در روش جدید:
۱. اولین باری که یکی از این اشیاء پیدا میشود، کل بلوک در صف میرود.
۲. تا وقتی نوبت اسکن آن بلوک میرسد، ممکن است ۵ یا ۶ شیء دیگر هم داخل همان بلوک علامت خورده باشند.
۳. در یک مرحله، همهی این اشیاء پشتسرهم اسکن میشوند. یعنی دسترسی به حافظه پشتسر هم و دوستداشتنی برای کش CPU.
اگر در یک بلوک فقط یک شیء برای اسکن وجود داشته باشد، بلوک را کامل اسکن نمیکنیم. فقط «نماینده» بلوک را بررسی میکنیم. اینطوری در بدترین حالت، از الگوریتم قدیمی عقب نمیافتیم.
تیم گوگل این GC جدید را روی ماشینهای ۱۶ هستهای تا ۸۸ هستهای آزمایش کرده:
در بنچمارکهای سنگین مثل garbage و binary-trees: بین ۱۰ تا ۵۰٪ کاهش مصرف CPU مربوط به GC. هرچه هسته بیشتر، نتیجه بهتر.
در Tile38 (یک پایگاه داده جغرافیایی در حافظه): ۳۵٪ کاهش سربار GC.
در Bleve-index (درخت دودویی که مدام چرخش میخورد): در ۱۶ هسته ۲٪ افت، اما در ۸۸ هسته بهبود. علت: چرخش درخت، اشیاء را به هم میریزد و locality را از بین میبرد. خود مقاله اعتراف کرده: «چای سبز وقتی خوب کار میکند که خود برنامه locality داشته باشد. نمیتواند از هیچ، locality بسازد.»
کامپایلر خود Go: تقریباً بدون تغییر.
چای سبز جادو نمیکند. اگر برنامه شما دائماً ساختار داده را بههم میریزد (مثل درختهایی که مرتباً Rotate میشوند)، اشیاء مرتبط از هم دور میافتند و مزیت locality از بین میرود. در این حالت، GC جدید ممکن است حتی چند درصد هم پس بزند.
چون اکنون بهجای اشیاء تکی، بلوکها را اسکن میکنیم، میتوانیم از دستورات SIMD (مثل AVX-512) استفاده کنیم تا چندین شیء را با یک دستور CPU اسکن کنیم. نمونههای اولیه نشان دادهاند که میتوان ۱۵-۲۰٪ دیگر سربار GC را کاهش داد.
اگر برنامه شما:
اشیاء کوچک زیاد تخصیص میدهد.
دسترسی به حافظه نسبتاً محلی دارد (نه کاملاً تصادفی).
روی ماشینهای با بیش از ۱۶ هسته اجرا میشود.
حتماً در Go 1.25 که اواسط ۲۰۲۶ منتشر میشود، این ویژگی را با GOEXPERIMENT=greentea فعال کنید.
اگر برنامه شما پر از درختهای دودویی شدیداً متعادلشونده است، با احتیاط آزمایش کنید.
این قابلیت هماکنون در Go 1.25 به صورت آزمایشی موجود است و گوگل آن را «آماده برای محیط تولید» میداند. تیم Go از شما بازخورد میخواهد.
پیوند به متن اصلی: (لینک مستندات Go یا ریپازیتوری مربوطه را اگر دارید بگذارید. اگر نه، همین جمله کافی است: «برگرفته از مستندات رسمی تیم Go، بهروزرسانی ۱۵ آگوست ۲۰۲۵»)