بینابندی رشته‌ها

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

تک نسخه هر رشته، بینابندی (intern) آن رشته نامیده می‌شود و معمولا توسط روش در کلاس رشته جستجو می‌شود. برای نمونه، ()String.intern در جاوا. با استفاده از این روش تمامی رشته‌های ثابت زمان کامپایل در جاوا به‌طور خودکار بینابندی می‌شوند.

برخی زبان‌های برنامه‌نویسی شیء‌گرای امروزی، از جمله جاوا، پایتون، پی‌اچ‌پی (از ورژن ۵.۴)، لوآ، و زبان‌های دات‌نت، همگی از بینابندی رشته‌ها پشتیبانی می‌کنند. لیسپ، اسکیم، جولیا، روبی، و اسمال‌تاک از جمله زبان‌های دارای داده‌های نوع سمبل هستند، که اساسا همان رشته‌های بینابندی‌شده هستند. کتابخانه استاندارد ام‌ال نیوجرسی دارای نوع داده اتم است که همان کار را انجام می‌دهد. انتخابگرهای (selector) آبجکتیو-سی، که عمدتاً به‌عنوان نام متدها استفاده می‌شوند، رشته‌های بینابندی شده‌اند.

اشیاء غیر از رشته‌ها می‌توانند بینابندی شوند. برای نمونه در جاوا، زمانی که مقادیر اولیه (primitive) درون یک شیء لفاف (wrapper) باکسینگ شوند (boxing)، مقادیر مشخصی (هر نوع داده بولی (`boolean``)`، بایتی (`byte``)`، کاراکتری (`char`) از ۰ تا ۱۲۷، و هر نوع داده کوتاه (`short`) یا عدد صحیح (`int`) بین ۱۲۸- و ۱۲۷) بینابندی می‌شوند، و برای هر دو تبدیل باکسینگ برای یک مقدار از این نوع، تضمین می‌شود که به یک شیء یکسان منجر شوند.

## تاریخچه
لیسپ، مفهوم رشته‌های بینابندی‌شده را برای سمبل‌های خود معرفی کرد. از بعد تاریخی، ساختار داده‌ای که به‌عنوان مخزن رشته‌ای استفاده می‌شد، زمانی که به‌صورت یک لیست پیوندی پیاده‌سازی شود، یک *oblist* و زمانی که به صورت یک آرایه پیاده‌سازی شود، یک *obarray* نام داشت.

انواع امروزی از زبان لییسپ معمولاً سمبل‌ها و رشته‌ها را تمیز می‌دهند؛ بینابندی یک رشته، سمبلی موجود باز می‌گرداند و یا سمبلی جدید می‌سازد، که آن سمبل نام همان رشته را دارد. سمبل‌ها اغلب توانایی‌های اضافه‌ای دارند که رشته‌ها آن‌ها را ندارند، مانند ذخیره مقادیر وابسته، یا ایجاد فضای نام. این تمایز همچنین برای جلوگیری از مقایسه تصادفی یک رشته بینابندی‌شده با رشته‌ای که لزوماً بینابندی نشده است، مفید است؛ که این اشتباه ممکن است، بسته به الگوهای استفاده، منجر به شکست‌های متناوب شود.

## انگیزه‌ها
بینابندی رشته‌ها موجب سرعت بخشیدن به مقایسه رشته‌ها می‌شود؛ عملیاتی که گاهی به یک گلوگاه عملکردی در برنامه‌هایی تبدیل می‌شود (مانند کامپایلرها یا محیط‌های اجرایی زبان‌های پویا) که برای جستجوی ویژگی‌ها و متدهای یک شیء، به‌شدت به آرایه‌های انجمنی با کلیدهای رشته‌ای متکی هستند. بدون بینابندی، مقایسه دو رشته متمایز ممکن است نیازمند برسی هر حرف از آن دو باشد. این کار به دو دلیل کند است: این عمل ذاتاً از مرتبه O(n) در طول رشته‌ها است؛ این عمل معمولاً نیازمند خواندن از چندین منطقه از حافظه است، که زمان نیاز دارد؛ و خواندن آن‌ها کش پردازشگر را پر می‌کند، به این معنی که فضای کش کمتری برای نیازهای دیگر موجود است. با رشته‌های بینابندی‌شده، یک آزمون هویت شیء بعد از عملیات بینابندی اصلی کافی است؛ که معمولاً به‌صورت یک آزمون برابری اشاره‌گر پیاده‌سازی می‌شود، و فقط یک دستور ماشین بدون هیچ ارجاعی به حافظه است.

زمانی که موارد زیادی از یک مقدار رشته وجود داشته باشد، بینابندی رشته‌ها موجب کاهش استفاده از حافظه می‌شود؛ برای مثال از یک شبکه یا حافظه خوانده می‌شود. چنین رشته‌هایی ممکن است شامل اعداد جادویی یا اطلاعات پروتکل شبکه باشند. برای نمونه تجزیه کننده‌های XML می‌توانند نام پلاک‌ها (tag)و صفات (attributes) را برای صرفه جویی در حافظه بینابندی کنند. انتقال شبکه‌ای اشیاء از جریان‌های شیء سریال‌سازی RMI جاوا می‌تواند رشته‌های بینابندی‌شده را به‌طرز بهینه‌تری انتقال دهند، از آن‌جایی که به‌محض سریال‌سازی شدن، شیء رشته‌ای دسته‌ای به‌جای اشیاء تکراری استفاده می‌شوند.

## مشکلات

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

مغایرت هم می‌تواند با تقسیم‌بندی فضای رشته به چندین مخزن کاهش یابد، که می‌توانند مستقل از یکدیگر هماهنگ شوند.

### بازپس‌گیری رشته‌های بینابندی‌شده بدون استفاده
بسیاری از پیاده‌سازی‌های رشته‌های بینابندی‌شده اقدام به بازپس‌گیری (به‌طور دستی یا غیردستی) رشته‌هایی که دیگر استفاده نمی‌شوند، نمی‌کنند. در برنامه‌هایی که تعداد رشته‌های بینابندی‌شده در آن‌ها کم یا ثابت باشند، یا دارای عمری کوتاه باشند، هدررفت منابع سامانه قابل چشم‌پوشی است. ولی برای برنامه‌های دارای مدت‌زمان اجرایی طولانی که در زمان اجرای آن‌ها تعداد زیادی بینابندی رشته تولید می‌شوند، نیاز به بازپس‌گیری بینابندی‌های بلااستفاده افزایش می‌یابد. این کار می‌تواند توسط یک زباله‌روب انجام شود، هرچند برای این‌که این روش درست کار کند، ارجاعات ضعیف به بینابندی‌های رشته باید در مخزن بینابندی ذخیره شوند.

## جستارهای وابسته

* الگوی مگس وزن

## منابع

## پیوند به بیرون

* Visual J# String class
* .NET String Class
* Guava Java Library - Interner - Non-permgen String.intern and supports other immutable types with weak and strong referenced implementation
* Understanding Java's intern() Method for Strings

رده:بهینه‌سازی نرم‌افزار
رده:رشته (علوم رایانه)