هشهای کوچیک روبی روی رژیم حافظه
خلاصهٔ کاملتر
نویسنده که روی مصرف حافظهٔ روبی کار میکنه، میگه بعد از بهبود Copy-on-Write بزرگترین فرصت باقیمونده حافظهٔ گذراست: حافظهای که تو دل یه ریکوئست یا جاب گرفته میشه و زود هم آزاد میشه. پرمصرفترین عضو این دسته هم Hashه — از آپشنهش و کیورد آرگومنت تا لاگ و پاسخ API — و به گفتهٔ اون همونقدر که راحته، همونقدر هم از نظر حافظه بیصرفهست.
اندازهگیریش سخت نیست؛ ObjectSpace.memsize_of اندازهٔ هر آبجکت رو میده:
require 'objspace'
ObjectSpace.memsize_of({})
# => 160یه هش خالی ۱۶۰ بایت جا میگیره، ولی همون کار با Struct یا یه آبجکت ساده ۴۰ تا ۸۰ بایت درمیاد — یعنی هش ۲ تا ۴ برابر سنگینتره. نکتهٔ کمتر واضح اینه که تا سایز ۸، هش روبی اصلاً هشتیبل نیست.
تاریخچهش پرفراز و نشیبه. تو روبی ۲.۴ ولادیمیر ماکاروف کل هشتیبل رو با open addressing بازنویسی کرد؛ سریعتر شد ولی هدر st_table از ۴۸ به ۵۶ بایت رفت. تو ۲.۶ هشهای تا ۸ عضو با ar_table عملاً به آرایهٔ خطی تبدیل شدن، چون اندازهگیری بنچمارکها نشون داد ۸۰٪ هشها ۸ عضو یا کمتر دارن. تو ۲.۷ هم با ذخیرهٔ فقط بایت پایین هشکد، ۷ بایت از هر عضو کم شد.
جهش بعدی Variable Width Allocation تو روبی ۳.۳ بود: اسلات آبجکتها از ۴۰ بایت ثابت به اندازههای ۴۰، ۸۰، ۱۶۰، ۳۲۰ و ۶۴۰ رسید، پس ar_table تونست داخل خود اسلات بشینه و پوینتر اضافه حذف شد — دقیقاً ۱۶۰ بایت. سود پنهانش اینه که GC دیگه free() صدا نمیزنه و فقط اسلات رو آزاد علامت میزنه. عوضش هش خالی چهار برابر قبل شد.
کف تئوری یه هش کوچیک ۳۲ بایت بهعلاوهٔ ۱۶ بایت برای هر عضوه، ولی دو مانع داره: گرد شدن به اندازههای اسلات GC، و اینکه هر هش باید بتونه به st_table رشد کنه. سه تغییر تازه این قید رو شکسته — اسلاتهای مضرب ۳۲ تا ۱۰۲۴ تو 4.1.0dev، آب رفتن st_table به ۴۸ بایت تو روبی ۴، و رفتن اندازهٔ اسلات داخل هدر آبجکت. نقطهٔ شروع هم هشهای فریزشدهست، چون وقتی تغییرناپذیرن نگرانی رشد ندارن:
DEFAULT_OPTIONS = {
host: "localhost",
port: 3456,
}.freezeنکات کلیدی:
- یه هش کوچیک تو روبی ۱۶۰ بایت میگیره، ۲ تا ۴ برابر Struct یا یه آبجکت ساده
- تا ۸ عضو، هش روبی با ar_table یه آرایهٔ خطیه، نه هشتیبل واقعی
- Variable Width Allocation تو ۳.۳ هش کوچیک رو ۱۶۰ بایت کرد و کار GC رو هم سبکتر کرد
- اسلاتهای مضرب ۳۲ و st_table ۴۸ بایتی تو روبی ۴ راه اسلاتهای کوچیکتر رو باز کردن
- هشهای فریزشده، مثل نسخهٔ پنهان duphash یا لیترال freezeشده، اولین هدف این بهینهسازیان
- هر جا Struct یا یه آبجکت ساده کافیه، همونو بردار




