گسترش در خط

در علوم کامپیوتر گسترش در خط به معنی جایگزینی دستور فراخوانی یک تابع با متن خود آن تابع است. این کار به صورت
دستی توسط برنامه‌نویس (به‌طور مثال به وسیله کلیدواژه‌های تعریف‌شده زبان) یا به صورت خودکار (توسط
کامپایلر) انجام می‌شود.
این عمل بسیار شبیه به گسترش ماکرو است، ولی تفاوت عمدهای که گسترش در خط
دارد این است که در زمان کامپایل انجام می‌شود ولی جایگزینی ماکروها در زمان پیش از کامپایل صورت
می‌گیرد و متن برنامه ورودی تحلیل‌گر کامپایلر تغییر پیدا می‌کند. مزیت گسترش در خط نسبت به ماکرو این
است که ایرادهای ماکرو را از قبیل احتمال رعایت نشدن اولویت عملیات ریاضی ندارد.
گسترش در خط تأثیر زیادی بر عملکرد کامپایلر دارد  و یکی از بهینه‌سازی‌های ساده در کامپایلرها است که می‌تواند منجر به افزایش سرعت شود. البته گسترش در خط بیش از حد به دلیل اشغال کردن قسمت عمده‌ای حافظه نهان دستورها ممکن است باعث کندتر شدن برنامه گردد. بررسی عملکرد گسترش در خط در مقاله‌های دهه ۸۰ تا ۹۰ میلادی در سال ۱۹۹۹ توسط Jones و Marlow انجام شده‌است
.

بررسی کلی

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

تأثیر آن بر روی عملکرد برنامه

گسترش در خط سر بار فراخوانی تابع را کاهش می‌دهد ولی دلیل اصلی انجام آن زمینه‌سازی برای بهینه‌سازی‌های دیگر است زیرا گسترش در خط اندازه برنامه را زیاد می‌کند و بهینه‌سازی‌های بهتری بر روی برنامه‌های با اندازه بزرگتر قابل انجام است
.
پیش‌بینی اثر نهایی گسترش در خط بر روی عملکرد برنامه پیچیده‌است و به دلیل اثر آن بر روی حافظه نهان دستورها، بسته به برنامه و اندازه حافظه نهان متفاوت است
.
همچنین میزان این تأثیر بین زبان‌های مختلف متفاوت است. به‌طور مثال در زبان‌های سطح پایین مانند C و Fortran، به اندازه ۱۰–۲۰٪ افزایش سرعت مشاهده می‌شود، در حالی که در زبان‌های سطح بالاتر و انتزاعی‌تر گسترش در خط می‌تواند چندین مرحله از اجرای برنامه را حذف کند. مثال این‌گونه زبان‌ها، زبان سلف (زبان_برنامه‌نویسی) است که ضریب بهبودی بین ۴ تا ۵۵ داشته‌است
.

پیاده‌سازی

پس از تشخیص اینکه کدام توابع باید گسترش در خط داده شوند، انجام این عمل معمولاً ساده است. کامپایلر می‌تواند که این عمل را در یک نمایش میانی سطح بالا مانند درخت نحو انتزاعی انجام دهد یا اینکه گسترش در خط در سطح پایین صورت گیرد. در هر دو حالت کامپایلر ورودی‌های تابع را حساب می‌کند، آن‌ها را در متغیرهایی قرار می‌دهد و در نهایت متن تابع را با محل فراخوانی آن تابع، جایگزین می‌کند.
پیوند دهندهها نیز می‌توانند گسترش در خط انجام دهند. پیونددهنده‌ها توابعی را که از کتابخانه‌های دیگر استفاده شده و در متن برنامه اولیه موجود نبوده را گسترش در خط می‌دهند.
در مثال زیر یک گسترش در خط به صورت دستی انجام شده‌است:
int pred(int x) {
    if (x == 0)
       return 0;
    else
       return x - 1;}
قبل از در خط سازی:
 int f(int y) {
     return pred(y) + pred(0) + pred(y+1);
 }
بعد از آن:
int f(int y) {
    int temp;
    if (y   == 0) temp  = 0; else temp  = y       - 1; /* (1) */
    if (0   == 0) temp += 0; else temp += 0       - 1; /* (2) */
    if (y+1 == 0) temp += 0; else temp += (y + 1) - 1; /* (3) */
    return temp;}