Кіріспе

Функция шақыруын сол функцияның бастапқы кодымен алмастыруды оңтайландыру. Есептеуде, желілік кеңейту немесе инлайнинг – функция шақыру орнын шақырылған функцияның мәтінімен алмастыратын қолмен немесе компилятордың оңтайландыруы. Желілік кеңейту макро кеңейтуге ұқсас, бірақ ол компиляция кезінде жүзеге асырылады және бастапқы кодты (мәтінді) өзгертпейді, ал макро кеңейту компиляциядан бұрын болады және компилятор өңдейтін басқа мәтінді құрайды. Инлайнинг маңызды оңтайландыру болып табылады, бірақ өнімділікке күрделі әсер етеді. Қағида бойынша, шамалы инлайнинг жылдамдықты минимал көлем шығынымен жақсартады, бірақ шамадан тыс инлайнинг жылдамдықты төмендетеді, себебі инлайн код тым көп нұсқаулық кэшін пайдаланады және айтарлықтай орынды қажет етеді. 1980 және 1990 жылдардағы инлайнинг туралы шағын академиялық әдебиеттерге шолу Peyton Jones & Marlow 1999 жұмысында келтірілген.

Шолу

Инлайн кеңейту макро кеңейтуге ұқсас, себебі компилятор функцияның жаңа көшірмесін оның шақырылған әрбір орнына қояды. Инлайн функциялар әдеттегі функциялардан сәл жылдам жұмыс істейді, себебі функцияны шақыруға байланысты қосымша шығындар жойылса да, жад тұтынуы артады. Егер функция 10 рет инлайн болса, кодқа функцияның 10 көшірмесі енгізіледі. Сондықтан инлайнинг жиі шақырылатын кіші функциялар үшін тиімді. C++-та, егер сыныптың мүше функциялары сынып анықтамасының ішінде берілсе, олар әдепкі бойынша инлайн болады (инлайн кілт сөзін пайдалану қажет емес); әйтпесе, кілт сөз қажет. Компилятор бағдарламашының функцияны инлайнға салу әрекетін қабылдамауы мүмкін, әсіресе функция өте үлкен болса. Функция шақырылғанда болатын уақыт шығынын (артық уақытты) жою үшін инлайн кеңейту қолданылады. Ол көбінесе жиі орындалатын функциялар үшін қолданылады. Бұған қоса, өте кішкентай функциялар үшін жадты үнемдеуге және басқа оңтайландыруларға мүмкіндік береді. Инлайн функциялар болмаса, компилятор қай функцияларды инлайнға қосу керектігін шешеді. Бағдарламашы инлайнға қосылатын және қосылмайтын функцияларды бақылауға ие болмайды. Бағдарламашыға осы деңгейдегі бақылау беру, қай функцияларды инлайнға қосу керектігін таңдауда қолданбаға тән білімді пайдалануға мүмкіндік береді. Кәдімгі жағдайда, функция шақырылғанда, басқару тармақ немесе шақыру нұсқаулығы арқылы оның анықтамасына беріледі. Инлайн болғанда, басқару функцияның кодына тікелей түседі, тармақ немесе шақыру нұсқаулығысыз. Компиляторлар әдетте инлайнингпен бірге операторларды іске асырады. Цикл шарттары мен цикл денелеріне ленивый бағалау қажет. Бұл қасиет цикл шарттарын және цикл денелерін есептеу коды инлайн болған кезде орындалады. Орындалу мәселелері – инлайнингтің тағы бір себебі. Функционалдық бағдарламалау тілдерінде инлайн кеңейту әдетте бета-редукция трансформациясымен жүзеге асырылады. Бағдарламашы бастапқы кодқа бір реттік операция ретінде функцияларды көшіру-қою арқылы қолмен инлайнға түсіруі мүмкін. Дегенмен, инлайнингті басқарудың басқа әдістері (төменде қараңыз) артықшылықты, себебі олар бағдарламашы бастапқы функцияның (мүмкін өзгертілген) көшірмесін қадағалауды ұмытқан кезде туындайтын қателерге әкеп соқпайды.

Компиляторды қолдау

Компиляторлар функция шақыруларын инлайнға қосу қажеттігін анықтау үшін әртүрлі механизмдерді пайдаланады; оларға бағдарламашылардан нақты функциялар үшін қолмен берілетін ұсыныстар және командалық жол опциялары арқылы жалпы басқару кіреді. Көптеген тілдердегі көптеген компиляторлар инлайнды автоматты түрде жасайды, бұл инлайнның тиімділігіне байланысты, ал кейбір жағдайларда оны компилятор директивалары арқылы қолмен, әдетте "inline" кілт сөзі немесе компилятор директивасын пайдалана отырып, көрсетуге болады. Әдетте, мұндай ұсыныс инлайнды міндетті етудің орнына, тек қана инлайн қаланын көрсетеді, және осы ұсыныстың күші тіл мен компиляторға қарай өзгереді. Компиляторды жасаушылар әдетте жоғарыда аталған өнімділік мәселелерін ескереді және компиляторларына эвристикалық алгоритмдерді енгізеді, олар көбінесе өнімділікті нашарлатудың орнына, жақсарту үшін қай функцияларды инлайнға қосуды таңдайды.

Шектеулер

Толық желідегі кеңейту рекурсияға байланысты әрқашан мүмкін емес: рекурсивті түрде кеңейтілген шақырулар тоқтамайды. Шешімдердің әртүрлі түрлері бар, мысалы, белгілі бір мөлшерде кеңейту немесе шақыру графигін талдап, белгілі бір түйіндерде циклдарды үзу (яғни, рекурсивті циклдегі кейбір байланысты кеңейтпеу). Дәл осындай мәселе макро кеңеюде де кездеседі, себебі рекурсивті кеңею аяқталмайды және әдетте рекурсивті макроларға тыйым салу арқылы шешіледі (C және C++ тілдеріндегідей).

Макролармен салыстыру

Дәстүрлі түрде, C сияқты тілдерде, сызықтық кеңейту параметрленген макростарды пайдалану арқылы бастапқы код деңгейінде жүзеге асырылды. C99 стандартында қолжетімді нақты сызықты функцияларды пайдалану, осы тәсілге қарағанда бірнеше артықшылықтар ұсынады: C тілінде макро шақырулары типтік тексеруді немесе аргументтердің дұрыс құрылғанын тексермейді, ал функция шақырулары көбінесе осы тексерулерді жүзеге асырады. C тілінде макрос, функция сияқты мағынада қайтару кілт сөзін пайдалана алмайды (ол макросты кеңейтуді сұраған функцияны тоқтатады, макростың өзі емес). Басқаша айтқанда, макрос өзінің ішіндегі соңғы өрнектің нәтижесінен басқа ештеңе қайтара алмайды. C макростары қарапайым мәтіндік алмастыруды қолданғандықтан, бұл аргументтердің қайта бағалануынан және операциялардың ретінен туындаған күтпеген жанама әсерлерге және тиімсіздікке әкелуі мүмкін. Макролардағы компилятор қателерін түсіну қиын, өйткені олар бағдарламашы жазған кодқа емес, кеңейтілген кодқа сілтеме жасайды. Сондықтан, сызықты кодты жөндеу туралы ақпарат, макро кеңейтілген кодты жөндеуге қарағанда көбінесе пайдалы болады. Көптеген конструкцияларды макростарды пайдалану арқылы түсіндіру қиын немесе мүмкін емес, немесе олар үшін едәуір өзгеше синтаксис қолданылуы керек. Сызықты функциялар, қалыпты функциялар сияқты бірдей синтаксисті пайдаланады және қалауынша оңай сызықты және сызықсыз етуге болады. Көптеген компиляторлар кейбір рекурсивті функцияларды да сызықты кеңейтуге мүмкіндік береді; ал рекурсивті макростар көбінесе рұхсат етілмейді. C++ тілінің жасаушысы Бьярне Строуструп, макростарды мүмкіндігінше болдырмау қажет екенін баса айтады және сызықты функцияларды кеңінен пайдалануды қолдайды.

Таңдау әдістері

Көптеген компиляторлар функцияларды пайдалы болған жағдайларда белсенді түрде ішке енгізеді. Бұл орындалатын файлдардың көлемін арттырса да, жад сыйымдылығы процессор жылдамдығынан тез өскендіктен, белсенді енгізуге деген қажеттілік артып келеді. Ішке енгізу – функционалдық және объектіге бағытталған бағдарламалау тілдеріндегі маңызды оптимизация, олар дәстүрлі оптимизацияларды тиімді ету үшін әдетте кішкентай функцияларына қажетті контексті қамтамасыз етуге сенеді.

C және C++

C және C++ тілдерінде inline кілт сөзі бар, ол компиляторға нұсқау ретінде қызмет етеді – inlining қажет екенін, бірақ міндетті емес екенін көрсетеді, сонымен қатар функцияның көріну қасиетін және байланыс әрекетін өзгертеді. Көріну қасиетін өзгерту стандартты C құралдар жинағы арқылы функцияны inlining-ке мүмкіндік беру үшін қажет, онда жеке файлдардың (немесе аударма бірліктерінің) компиляциясынан кейін байланыс жасалады: байланыс құралына функцияларды inlining-ке мүмкіндік беру үшін, олар header-де (көріну үшін) көрсетілуі керек және inline деп белгіленуі керек (көптеген анықтамалардан туындайтын екіұштылықты болдырмау үшін).