رفتن به محتوای اصلی
توضیح کوهستانساختار دادهگزارش تحلیلی· 4 دقیقه مطالعه· در فناوری

چرا هش‌مپ‌ها به‌طور پیش‌فرض روی ضریب بار ۰٫۷۵ تنظیم می‌شوند و چه زمانی باید آن را تغییر داد

ضریب بار همه‌گیر ۰٫۷۵ در هش‌مپ‌ها یک محدودیت سخت‌افزاری نیست، بلکه یک مصالحه ریاضی بر اساس توزیع پواسون است. درک این آستانه به توسعه‌دهندگان اجازه می‌دهد تا در زمان افت عملکرد پیش‌فرض، حافظه را فدای سرعت کنند.

به قلم کاوان رامین

این خبر را به اشتراک بگذارید

به‌طور خلاصه

  • هش‌مپ‌ها در صورت بروز برخوردهای مکرر که پردازنده را مجبور به پیمایش لیست‌های پیوندی می‌کند، سرعت جستجوی O(1) را تضمین نمی‌کنند.
  • ضریب بار ۰٫۷۵ تعیین می‌کند که وقتی یک مپ تا ۷۵ درصد پر شد، باید اندازه خود را دو برابر کرده و همه ورودی‌ها را دوباره هش کند.
  • این آستانه از توزیع پواسون استخراج شده است تا تعادلی میان سربار حافظه و احتمال برخورد ایجاد کند.

برنامه‌های درسی علوم کامپیوتر و مستندات کتابخانه‌های استاندارد اغلب هش‌مپ‌ها را به‌عنوان یک مشکل حل‌شده بازاریابی می‌کنند و جستجوهای زمان ثابت O(1) را فارغ از مقیاس مجموعه داده‌ها تضمین می‌کنند. اما واقعیت ریاضی ضریب بار ۰٫۷۵ — همان آستانه کدگذاری‌شده‌ای که زمان تغییر اندازه این ساختارهای داده را کنترل می‌کند — ثابت می‌کند که این ادعا به‌شدت مشروط است.[1]

برای درک اینکه چرا این تضمین در هم می‌شکند، باید به سازوکار زیربنایی آن نگاه کرد. وقتی یک توسعه‌دهنده یک جفت کلید-مقدار را در یک مپ وارد می‌کند، یک تابع هش، کلید را به یک عدد صحیح تبدیل می‌کند. آن عدد صحیح تعیین می‌کند که کدام «سطل» (bucket) خاص در یک آرایه، داده‌ها را ذخیره خواهد کرد.[2]

از آنجا که جهان کلیدهای ممکن عملاً بی‌نهایت است در حالی که آرایه سطل‌ها محدود است، دو کلید متمایز ناگزیر شاخص یکسانی تولید خواهند کرد. این رویداد به‌عنوان «برخورد هش» (hash collision) شناخته می‌شود و گلوگاه اصلی در عملکرد هش‌مپ است.[6]

هنگامی که یک برخورد رخ می‌دهد، مپ نمی‌تواند به‌سادگی داده‌های موجود را بازنویسی کند. در عوض، باید چندین ورودی را در یک سطل ذخیره کند و معمولاً آن‌ها را در یک لیست پیوندی به هم متصل می‌کند. اگر توسعه‌دهنده‌ای بخواهد کلیدی را از سطلی حاوی پنج ورودی بازیابی کند، سیستم باید آن لیست را یکی‌یکی بپیماید و سرعت جستجو را از O(1) به O(n) کاهش دهد.[2]

در ضریب بار ۰٫۷۵، احتمال اینکه یک سطل شامل بیش از هشت عنصر باشد از نظر آماری ناچیز است.

ضریب بار دقیقاً برای جلوگیری از طولانی شدن بیش از حد این زنجیره‌ها وجود دارد. این ضریب به‌عنوان نسبت ورودی‌های ذخیره‌شده به کل سطل‌های موجود تعریف می‌شود. ضریب بار ۰٫۷۵ دیکته می‌کند که وقتی مپ تا ۷۵ درصد پر شد، باید برای حفظ عملکرد خود گسترش یابد.[1]

این گسترش که با نام «هش‌کردن مجدد» (rehashing) شناخته می‌شود، یک عملیات بی‌رحمانه است. سیستم یک آرایه جدید — معمولاً دو برابر اندازه اصلی — تخصیص می‌دهد و شاخص هش را برای تک‌تک ورودی‌های موجود دوباره محاسبه کرده و آن‌ها را به مکان‌های جدیدشان منتقل می‌کند. در طول این فرآیند، برنامه عملاً متوقف می‌شود.[4]

انتخاب خاص ۰٫۷۵ به‌عنوان آستانه پیش‌فرض در زبان‌هایی مانند جاوا یک محدودیت سخت‌افزاری نیست، بلکه یک مصالحه آماری است. مستندات جاوا صراحتاً به توزیع پواسون برای توجیه این ثابت استناد می‌کنند.[5]

بر اساس این مدل ریاضی، اگر کدهای هش به‌طور یکنواخت توزیع شوند، تعداد عناصر در هر سطل از توزیع پواسون پیروی می‌کند. در ضریب بار ۰٫۷۵، احتمال اینکه یک سطل شامل بیش از هشت عنصر باشد به ۰٫۰۰۰۰۰۰۰۶ کاهش می‌یابد.[5]

همین احتمال خاص، لنگرگاه معماری هش‌مپ‌های مدرن است. در سال ۲۰۱۴، جاوا ۸ مکانیزمی را معرفی کرد که در آن هر سطلی که از هشت عنصر فراتر رود، لیست پیوندی را رها کرده و به یک درخت سرخ-سیاه (red-black tree) تبدیل می‌شود و بدترین زمان جستجو را از O(n) به O(log n) تغییر می‌دهد.[1]

توسعه‌دهندگان از نظر تئوری می‌توانند با تنظیم ضریب بار روی ۰٫۱، برخوردها را کاملاً از بین ببرند و مپ را مجبور کنند زمانی که تنها ۱۰ درصد پر است تغییر اندازه دهد. با این حال، این کار باعث تورم شدید حافظه می‌شود و ۹۰ درصد از آرایه تخصیص‌یافته را کاملاً خالی می‌گذارد.[3]

آستانه پیش‌فرض نشان‌دهنده تقاطع ریاضی است که در آن بهره‌وری حافظه و سرعت جستجو بهینه‌ترین تعادل را دارند.

آرایه‌های پراکنده همچنین یک جریمه عملکردی ثانویه در سطح سخت‌افزار ایجاد می‌کنند. پردازنده‌های مدرن حافظه را در خطوط کش ۶۴ بایتی واکشی می‌کنند. یک آرایه متراکم استفاده بهینه‌ای از این حافظه پنهان می‌کند، در حالی که یک آرایه پراکنده پردازنده را مجبور می‌کند دائماً خطوط جدیدی را از حافظه اصلی واکشی کند و تاخیری ایجاد می‌کند که مزیت برخوردهای کمتر را خنثی می‌سازد.[4]

در مقابل، ضریب بار ۱٫۰ بهره‌وری حافظه را به حداکثر می‌رساند اما نرخ بالای برخوردها را تضمین می‌کند و پردازنده را مجبور می‌سازد چرخه‌های خود را به‌جای اجرای منطق اصلی برنامه، صرف پیمایش لیست‌های پیوندی یا درخت‌های سرخ-سیاه کند.[6]

در حالی که نگهدارندگان زبان‌ها پیش‌فرض ۰٫۷۵ را به‌عنوان یک بهینه‌سازی همه‌جانبه معرفی می‌کنند، این عدد صراحتاً برای محاسبات همه‌منظوره تنظیم شده است. مهندسانی که سیستم‌های معاملاتی با تاخیر پایین یا موتورهای بازی‌سازی بلادرنگ می‌سازند، معمولاً آن را کنار می‌گذارند.[3]

هش‌کردن مجدد نیازمند تخصیص یک آرایه جدید با دو برابر اندازه اصلی و محاسبه مجدد شاخص برای هر ورودی ذخیره‌شده است.

در این محیط‌های با عملکرد بالا، توسعه‌دهندگان اغلب هش‌مپ‌ها را با ظرفیت اولیه دقیق و ضریب بار پایین‌تری مانند ۰٫۵ از پیش تخصیص می‌دهند تا تضمین کنند که هیچ‌گاه وقفه‌ای برای هش‌کردن مجدد در طول اجرا رخ نخواهد داد.[2]

ثابت ۰٫۷۵ همچنان استاندارد صنعت باقی مانده است، اما محصول زمانه خود است. با ارزان‌تر شدن حافظه‌های DDR5 و گسترش حافظه‌های پنهان L3 پردازنده‌ها به بیش از ۱۲۸ مگابایت، مفروضات ریاضی که تورم حافظه را در برابر تاخیر برخورد متعادل می‌کنند، ناگزیر تغییر خواهند کرد و طراحان زبان‌ها را مجبور به ارزیابی مجدد آستانه‌ای می‌کنند که بیش از دو دهه بر ساختارهای داده حاکم بوده است.[7]

اصطلاحات کلیدی

تابع هش
الگوریتمی که یک کلید داده را به یک شاخص عدد صحیح تبدیل می‌کند و تعیین می‌کند داده‌ها در کجای یک آرایه ذخیره شوند.
برخورد هش
رویدادی که زمانی رخ می‌دهد که دو کلید متمایز شاخص عدد صحیح یکسانی تولید کنند و دقیقاً به یک سطل اختصاص یابند.
هش‌کردن مجدد
فرآیند پرهزینه محاسباتی برای محاسبه مجدد شاخص سطل برای همه ورودی‌های ذخیره‌شده، زمانی که یک مپ ظرفیت خود را گسترش می‌دهد.
توزیع پواسون
یک مدل آماری که برای پیش‌بینی احتمال وقوع تعداد معینی از رویدادها در یک بازه ثابت استفاده می‌شود و در اینجا برای مدل‌سازی نرخ برخورد به کار می‌رود.

پرسش‌های متداول

وقتی یک هش‌مپ از ضریب بار خود فراتر می‌رود چه اتفاقی می‌افتد؟

ساختار داده یک رویداد تغییر اندازه را آغاز می‌کند، آرایه جدیدی تخصیص می‌دهد که معمولاً دو برابر بزرگ‌تر است و شاخص هش را برای هر ورودی موجود دوباره محاسبه می‌کند تا آن‌ها را به آرایه جدید منتقل کند.

آیا توسعه‌دهندگان می‌توانند ضریب بار پیش‌فرض را تغییر دهند؟

بله. بیشتر زبان‌ها، از جمله جاوا، به توسعه‌دهندگان اجازه می‌دهند هنگام مقداردهی اولیه هش‌مپ، یک ضریب بار و ظرفیت اولیه سفارشی را مشخص کنند.

چرا از ضریب بار ۱٫۰ استفاده نمی‌شود؟

ضریب بار ۱٫۰ بهره‌وری حافظه را به حداکثر می‌رساند اما برخوردهای مکرر هش را تضمین می‌کند، که پردازنده را مجبور به پیمایش لیست‌های پیوندی کرده و سرعت جستجو را از زمان ثابت به زمان خطی کاهش می‌دهد.

بررسی عمیق دیدگاه‌ها

نگهدارندگان کتابخانه استاندارد

اولویت دادن به پیش‌فرض‌های ایمن و همه‌منظوره که از اتمام حافظه جلوگیری کرده و در عین حال سرعت قابل‌قبولی را برای برنامه‌های متوسط حفظ می‌کنند.

طراحان زبان باید کتابخانه‌های استانداردی ارائه دهند که چه روی یک سرور ابری عظیم و چه روی یک دستگاه تعبیه‌شده با محدودیت حافظه اجرا شوند، رفتار قابل‌پیش‌بینی داشته باشند. برای این نگهدارندگان، ضریب بار ۰٫۷۵ نشان‌دهنده ایمن‌ترین حد وسط ریاضی است. این عدد تضمین می‌کند که برنامه‌ها رم بیش از حدی را با سطل‌های آرایه خالی مصرف نکنند، در حالی که احتمال آماری برخوردهای شدید هش را آن‌قدر پایین نگه می‌دارد که توسعه‌دهنده متوسط هرگز متوجه افت عملکرد نشود.

مهندسان تاخیر پایین

وقفه‌های ناشی از هش‌کردن مجدد را غیرقابل‌قبول می‌دانند و ترجیح می‌دهند با تخصیص پیشاپیش آرایه‌های پراکنده با ضرایب بار پایین‌تر، حافظه را هدر دهند.

در معاملات با فرکانس بالا یا رندرینگ بلادرنگ، یک رویداد ناگهانی هش‌کردن مجدد که برنامه را برای محاسبه مجدد یک میلیون شاخص عدد صحیح متوقف می‌کند، می‌تواند باعث افت فریم یا از دست رفتن یک معامله مالی شود. مهندسان در این حوزه‌ها پیش‌فرض ۰٫۷۵ را یک نقطه ضعف می‌دانند. آن‌ها معمولاً با تخصیص پیشاپیش هش‌مپ‌ها به حداکثر اندازه موردنیازشان با ضریب بار ۰٫۵ یا کمتر، این پیش‌فرض را دور می‌زنند و عمداً رم را هدر می‌دهند تا زمان‌های اجرای قطعی و عدم تغییر اندازه در میانه عملیات را تضمین کنند.

توسعه‌دهندگان محدود در حافظه

در محیط‌های تعبیه‌شده یا با تراکم بالا کار می‌کنند که در آن‌ها صرفه‌جویی در رم بسیار حیاتی‌تر از جلوگیری از سربار برخورد پردازنده است.

برای توسعه‌دهندگانی که نرم‌افزارهایی برای دستگاه‌های اینترنت اشیا، میکروکنترلرها یا محیط‌های کانتینری با تراکم بالا می‌نویسند، حافظه محدودیت سخت‌تری نسبت به چرخه‌های پردازنده است. این مهندسان اغلب ضریب بار را به ۰٫۹ یا ۱٫۰ نزدیک می‌کنند. در حالی که این کار نرخ بالاتری از برخوردهای هش را تضمین می‌کند و پردازنده را مجبور می‌سازد در طول جستجوها سخت‌تر کار کند، اما اطمینان می‌دهد که ردپای برنامه تا حد ممکن کوچک باقی بماند و از خرابی‌های ناشی از کمبود حافظه در دستگاه‌هایی با محدودیت‌های سخت‌افزاری شدید جلوگیری می‌کند.

نگهدارندگان کتابخانه استاندارد 40%مهندسان تاخیر پایین 40%توسعه‌دهندگان محدود در حافظه 20%
نگهدارندگان کتابخانه استاندارد
اولویت دادن به پیش‌فرض‌های ایمن و همه‌منظوره که از اتمام حافظه جلوگیری کرده و در عین حال سرعت قابل‌قبولی را برای برنامه‌های متوسط حفظ می‌کنند.
مهندسان تاخیر پایین
وقفه‌های ناشی از هش‌کردن مجدد را غیرقابل‌قبول می‌دانند و ترجیح می‌دهند با تخصیص پیشاپیش آرایه‌های پراکنده با ضرایب بار پایین‌تر، حافظه را هدر دهند.
توسعه‌دهندگان محدود در حافظه
در محیط‌های تعبیه‌شده یا با تراکم بالا کار می‌کنند که در آن‌ها صرفه‌جویی در رم بسیار حیاتی‌تر از جلوگیری از سربار برخورد پردازنده است.

دیدگاه‌هایی که این گزارش پوشش نداده

  • طراحان کامپایلر
  • معماران سخت‌افزار

منابع

پوشش منابع

7 منبع

3 دیدگاه شناسایی‌شده

نگهدارندگان کتابخانه استاندارد 40%مهندسان تاخیر پایین 40%توسعه‌دهندگان محدود در حافظه 20%
  1. [1]Baeldungتوسعه‌دهندگان محدود در حافظه

    Java HashMap Load Factor

    مطالعه در Baeldung →
  2. [2]DEV Communityمهندسان تاخیر پایین

    Hash Map Deep Dive

    مطالعه در DEV Community →
  3. [3]Experiments in program optimisationمهندسان تاخیر پایین

    Choosing the hash map's capacity

    مطالعه در Experiments in program optimisation →
  4. [4]Mediumتوسعه‌دهندگان محدود در حافظه

    Building a Fast, Memory-Efficient Hash Table in Java (by borrowing the best ideas)

    مطالعه در Medium →
  5. [5]Computer Science Stack Exchangeنگهدارندگان کتابخانه استاندارد

    Why is the Java HashMap load factor 0.75?

    مطالعه در Computer Science Stack Exchange →
  6. [6]Stack Overflowنگهدارندگان کتابخانه استاندارد

    What is the significance of load factor in HashMap?

    مطالعه در Stack Overflow →
  7. [7]تیم سردبیری کوهستان

    تحلیل تیم سردبیری کوهستان

    مطالعه در تیم سردبیری کوهستان →

نظرات

همیشه در جریان باشید

هر زاویه. هر روز.

اخبار فناوری با پوشش کامل منابع و تحلیل دیدگاه‌ها، هر روز و رایگان.