گسترش در خط
From Wikipedia, the free encyclopedia
From Wikipedia, the free encyclopedia
در علوم کامپیوتر گسترش در خط به معنی جایگزینی دستور فراخوانی یک تابع با متن خود آن تابع است. این کار به صورت دستی توسط برنامهنویس (بهطور مثال به وسیله کلیدواژههای تعریفشده زبان) یا به صورت خودکار (توسط کامپایلر) انجام میشود.
این عمل بسیار شبیه به گسترش ماکرو است، ولی تفاوت عمدهای که گسترش در خط دارد این است که در زمان کامپایل انجام میشود ولی جایگزینی ماکروها در زمان پیش از کامپایل صورت میگیرد و متن برنامه ورودی تحلیلگر کامپایلر تغییر پیدا میکند. مزیت گسترش در خط نسبت به ماکرو این است که ایرادهای ماکرو را از قبیل احتمال رعایت نشدن اولویت عملیات ریاضی ندارد.
گسترش در خط تأثیر زیادی بر عملکرد کامپایلر دارد [1] و یکی از بهینهسازیهای ساده در کامپایلرها است که میتواند منجر به افزایش سرعت شود. البته گسترش در خط بیش از حد به دلیل اشغال کردن قسمت عمدهای حافظه نهان دستورها ممکن است باعث کندتر شدن برنامه گردد. بررسی عملکرد گسترش در خط در مقالههای دهه ۸۰ تا ۹۰ میلادی در سال ۱۹۹۹ توسط Jones و Marlow انجام شدهاست [2].
همانطور که گفته شد گسترش در خط از گسترش ماکرو سریعتر است و دلیل آن این است که در گسترش در خط سر بار فراخوانی تابع (که شامل ذخیرهسازی مقادیر ثبّاتها و پرش است) دیگر وجود ندارد و خطوط مربوط به متن تابع مستقیماً اجرا میشود. از جهت دیگر اما گسترش در خط میتواند باعث هدر رفتن حافظه شود زیرا به ازای هر محل از برنامه که تابع فراخوانی شده باشد، یک رونوشت از متن تابع در آنجا اضافه میگردد. در نتیجه استفاده از گسترش در خط معمولاً در حالتی که متن تابع کوتاه است میتواند کارساز باشد.
بهطور مثال در زبان ++C، توابعی که عضو کلاسها هستند در صورتی که در داخل تعریف کلاس تعریف شوند بهطور پیشفرض در خط سازی میشوند. در غیر این صورت برنامهنویس میبایستی صراحتاً از کلیدواژه inline استفاده کند. همچنین دلیل اشاره شده بالا، کامپایلر این زبان، توابع بزرگی که برنامهنویس صراحتاً درخواست خطیسازی آنها را کردهاست، خطیسازی نمیکند.
همچنین در برنامهنویسی تابعی، گسترش در خط معمولاً پس از تبدیل کاهش بتا صورت میگیرد.
گسترش در خط سر بار فراخوانی تابع را کاهش میدهد ولی دلیل اصلی انجام آن زمینهسازی برای بهینهسازیهای دیگر است زیرا گسترش در خط اندازه برنامه را زیاد میکند و بهینهسازیهای بهتری بر روی برنامههای با اندازه بزرگتر قابل انجام است [3]. پیشبینی اثر نهایی گسترش در خط بر روی عملکرد برنامه پیچیدهاست و به دلیل اثر آن بر روی حافظه نهان دستورها، بسته به برنامه و اندازه حافظه نهان متفاوت است [1].
همچنین میزان این تأثیر بین زبانهای مختلف متفاوت است. بهطور مثال در زبانهای سطح پایین مانند C و Fortran، به اندازه ۱۰–۲۰٪ افزایش سرعت مشاهده میشود، در حالی که در زبانهای سطح بالاتر و انتزاعیتر گسترش در خط میتواند چندین مرحله از اجرای برنامه را حذف کند. مثال اینگونه زبانها، زبان سلف (زبان_برنامهنویسی) است که ضریب بهبودی بین ۴ تا ۵۵ داشتهاست [2].
کامپایلرها از روشهای مختلفی برای تشخیص اینکه چه تابعی را گسترش در خط دهند، استفاده میکنند. این روشها عبارتند از:
گسترش در خط در بسیاری از زبانها به صورت خودکار توسط کامپایلر صورت میگیرد و کامپایلر بررسی میکند که آیا این عمل برای سرعت برنامه مفید است یا خیر. همچنین کلیدواژههایی مانند inline نیز در برخی از زبانها به عنوان پیشنهادی از طرف برنامهنویس برای در خطی سازی تابع وجود دارد. هرچند که همانطور که گفته شد این کلیدواژهها کامپایلر را مجبور به انجام این عمل نمیکند.
بهطور کلی توسعهدهندگان کامپایلرها از الگوریتم جستجوی کاشف و روشهای مکاشفهای در طراحی کامپایلر استفاده میکنند تا تشخیص دهند که در چه جایی نیاز به گسترش در خط میباشد.
پس از تشخیص اینکه کدام توابع باید گسترش در خط داده شوند، انجام این عمل معمولاً ساده است. کامپایلر میتواند که این عمل را در یک نمایش میانی سطح بالا مانند درخت نحو انتزاعی انجام دهد یا اینکه گسترش در خط در سطح پایین صورت گیرد. در هر دو حالت کامپایلر ورودیهای تابع را حساب میکند، آنها را در متغیرهایی قرار میدهد و در نهایت متن تابع را با محل فراخوانی آن تابع، جایگزین میکند.
پیوند دهندهها نیز میتوانند گسترش در خط انجام دهند. پیونددهندهها توابعی را که از کتابخانههای دیگر استفاده شده و در متن برنامه اولیه موجود نبوده را گسترش در خط میدهند.
در مثال زیر یک گسترش در خط به صورت دستی انجام شدهاست:
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;
}
پیش از C99 در زبان سی در خط سازی به کمک ماکروها انجام میشد. مزایای گسترش در خط نسبت به ماکروها عبارتند از:
بییارنه استراستروپ خالق زبان سی پلاسپلاس نیز استفاده از توابع در خط را به جای ماکروها توصیه میکند.[4]
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.