Table of Contents

परिचय: पुनः मूल्यांकन समारोह कॉल ओवरहेड

C प्रोग्रामिंग में, प्रत्येक फ़ंक्शन कॉल ओवरहेड को पेश करता है: कम्पाइलर को स्टैक पर तर्कों को धक्का देना चाहिए (या उन्हें रजिस्टरों में पास करना), फ़ंक्शन बॉडी में कूदना, कोड को निष्पादित करना, और फिर वापस करना चाहिए। छोटे, अक्सर प्रेरित कार्यों के लिए, यह ओवरहेड निष्पादन समय पर हावी हो सकता है, विशेष रूप से प्रदर्शन-महत्वपूर्ण लूप या गहराई से घोंसले के संचालन में। आधुनिक कम्पाइलर आक्रामक रूप से अनुकूलन करते हैं, लेकिन कभी-कभी प्रोग्रामर को अधिकतम गति प्राप्त करने के लिए स्पष्ट संकेत प्रदान करना चाहिए। ऐसे संकेत [FLT: 0] कीवर्ड है, जो कम्पाइलर को कार्य के शरीर के साथ कॉल साइट को बदलने के लिए आमंत्रित करता है - एक तकनीक जिसे [FLT] में विपरीत कार्य को सक्षम करता है।

इनलाइन कार्यों के पीछे तंत्र

एक इनलाइन फ़ंक्शन को कीवर्ड के साथ घोषित किया गया है। यह कंपाइलर को इनलाइन करने के लिए कमांड नहीं करता है; यह एक सुझाव है। कंपाइलर उन कार्यों के लिए इसे अनदेखा कर सकता है जो बहुत बड़े, पुनरावर्ती हैं, या जब अनुकूलन स्तर कम हैं। C99 और बाद के मानकों में, के अर्थ को स्पष्ट किया गया: एक हेडर फ़ाइल में के साथ परिभाषित कार्य को दोहराव या लिंकिंग त्रुटियों के कारण कई अनुवाद इकाइयों में शामिल किया जा सकता है, बशर्ते कि एक गैर-इनलाइन बाहरी परिभाषा मौजूद है। यह अक्सर [FLT:] या] के संयोजन के साथ प्राप्त किया जाता है।

  • Static inline: इस समारोह में आंतरिक लिंकेज है; प्रत्येक अनुवाद इकाई अपनी प्रतिलिपि हो जाती है। यह हेडर में परिभाषित छोटे सहायक कार्यों के लिए सबसे सुरक्षित और सबसे पोर्टेबल दृष्टिकोण है।
  • Extern inline (C99): इनलाइन परिभाषा शरीर को inlining प्रदान करती है, लेकिन एक बाहरी परिभाषा अलग से (आमतौर पर एक .c फ़ाइल में) मौजूद होना चाहिए। C11 और बाद में, यह व्यवहार हार्मोनाइज्ड था।
  • ]]]Inline without stabilized or extern: C99 में, यह बाहरी इनलाइन के समान है; C11 में, बाहरी परिभाषाओं की आवश्यकता केवल तभी होती है जब समारोह inlined नहीं है। व्यावहारिक रूप से, ] को अधिकांश उपयोग मामलों के लिए पसंद किया जाता है।

की अंतर्दृष्टि: इनलाइनिंग एक मुफ्त दोपहर का भोजन नहीं है। कम्पाइलर लागत लाभ व्यापार-बंद का विश्लेषण करता है: प्रत्येक कॉल साइट पर एक समारोह के शरीर को डालने से कोड आकार (कोड ब्लॉट) बढ़ जाता है, जो अनुदेश कैश दक्षता को कम कर सकता है। इस प्रकार, इनलाइन को छोटे, अक्सर कार्यों के लिए आरक्षित किया जाता है।

जब इनलाइन फंक्शन्स एक्सेल: मामलों और सर्वश्रेष्ठ प्रथाओं का उपयोग करें

लघु गणितीय संचालन

उन कार्य जो प्राथमिक अंकगणित करते हैं - जैसे कि एक वर्ग की गणना करना, एक मूल्य को क्लैंप करना, या एक संकेत का परीक्षण करना - प्रधानमंत्री उम्मीदवार हैं। एक फ़ंक्शन कॉल का ओवरहेड अक्सर ऑपरेशन से ही बड़ा होता है। उदाहरण के लिए:

static inline int clamp(int value, int low, int high) {
 return (value < low) ? low : (value > high) ? high : value;
}

डाटा स्ट्रक्चर्स में एक्सेसर और म्यूटेटर कार्य

C में ऑब्जेक्ट-उन्मुख पैटर्न अक्सर डेटा को encapsulate करने के लिए गेटर्स और सेटर्स का उपयोग करते हैं। बिना किसी अन्य प्रकार के, इन परीक्षणों में अनावश्यक उपरिक् त होते हैं:

typedef struct {
 int x, y;
} Point;

static inline int point_get_x(const Point *p) {
 return p->x;
}

static inline void point_set_x(Point *p, int x) {
 p->x = x;
}

एम्बेडेड सिस्टम और रियल टाइम कोड

सीमित स्टैक स्पेस और नियत समय की आवश्यकताओं वाले वातावरण में, इनलाइन फंक्शन्स को पुश/पॉप स्टैक फ्रेम की आवश्यकता को समाप्त करते हैं, जिससे विलंबता और मेमोरी दोनों का उपयोग कम हो जाता है। हालांकि, कोड आकार को मेमोरी-संविदा माइक्रोकंट्रोलर पर सावधानीपूर्वक निगरानी रखना चाहिए।

]No] to Inline

  • ]बड़े कार्य: एकाधिक कॉल साइटों पर 100+ लाइन फ़ंक्शन को शामिल करने से निर्देश कैश दबाव के कारण द्विआधारी और संभावित गिरावट प्रदर्शन को धीमा कर देगा।
  • Recursive function: Recursion पूरी तरह से रेखांकित नहीं किया जा सकता (हालांकि कम्पाइलर कुछ स्तरों को अनरोल कर सकता है)।
  • ]]]]]]]]]]]]]]]एक बड़े पाश युक्त समारोह को शामिल करने के लिए महत्वपूर्ण लाभ प्रदान नहीं कर सकते हैं।
  • ]Rarely बुलाया कार्यों: ओवरहेड को लापरवाही है अगर समारोह को अक्सर बुलाया जाता है; केवल अपशिष्ट अंतरिक्ष को जलाना.

इनलाइन फंक्शन्स वर्सोस मैक्रो: ए विस्तृत तुलना

से पहले कीवर्ड मानक था, C प्रोग्रामर ने मैक्रोज़ (]]) का इस्तेमाल किया, ताकि "inlining" प्राप्त किया जा सके लेकिन मैक्रो टेक्स्ट प्रतिस्थापन हैं, कार्य नहीं करते हैं। वे गंभीर कमियों के साथ आते हैं:

  • type safety:] Macros प्रकार की उपेक्षा. Infamous मैक्रो तर्क एकाधिक बार मूल्यांकन, खतरनाक दुष्प्रभावों के लिए अग्रणी जब अभिव्यक्तियों के साथ इस्तेमाल किया ].
  • Dbugging: मैक्रोज़ प्रीप्रोसेसिंग के दौरान गायब हो जाते हैं; डीबगर उनमें नहीं कदम रख सकते हैं।
  • ]Compound बयान: मल्टी स्टेटमेंट मैक्रोज़ को बदसूरत वर्कअराउंड (जैसे, [[FLT: 13]]]]] की आवश्यकता होती है।
  • Name collisions: मैक्रो विस्तार स्थानीय चर के साथ हस्तक्षेप कर सकते हैं।

इन सभी मुद्दों को इनलाइन कार्यों को पार करते हैं: वे टाइप चेकिंग, गुंजाइश और साइड-प्रभाव-सुरक्षा तर्क मूल्यांकन के साथ सही कार्य करते हैं। वे नियमित प्रकार प्रणाली में भाग लेते हैं और उन्हें डिबग किया जा सकता है। मैक्रोज़ का एकमात्र सैद्धांतिक लाभ यह है कि उनका उपयोग type-generic के लिए किया जा सकता है।

] अंगूठे का नियम: Prefer किसी भी तर्क के लिए मैक्रोज़ पर कार्य करता है जो एक कार्य हस्ताक्षर फिट बैठता है। रिजर्व मैक्रो केवल सरल स्थिरांक या टोकन पेस्टिंग के लिए।

व्यावहारिक उदाहरण: एक्शन में इनलाइन कार्य

उदाहरण 1: स्क्वायर (अल्रीकी प्रदान की गई)

static inline int square(int x) {
 return x * x;
}

कम्पाइलर की संभावना सभी पर कॉल निर्देश नहीं देना चाहिए; कोड प्रत्येक कॉल साइट पर बस हो जाता है।

उदाहरण 2: जाँच अगर एक चरित्र एक अंक है

static inline int is_digit(char c) {
 return c >= '0' && c <= '9';
}

उदाहरण 3: फास्ट मिन / मैक्स (Avoide Macros)

static inline int imax(int a, int b) {
 return (a > b) ? a : b;
}

मैक्रो संस्करण के विपरीत, यह मूल्यांकन ] और ]]] वास्तव में एक बार, डबल मूल्यांकन जोखिम से बचने के लिए।

उदाहरण 4: बिट ऑपरेशन (Unions or Byte Swapping)

static inline uint16_t swap_bytes(uint16_t x) {
 return (x << 8) | (x >> 8);
}

यह एक एकल के लिए संकलित करता है, एआरएम पर निर्देश, या जब इनलाइन किया जाता है तो x86 पर घुमाएं।

Compiler Optimizations and the Inline Keyword

] कीवर्ड केवल एक कारक है जो एक कम्पाइलर के झुकाव निर्णय में है। अधिकांश कम्पाइलर में कमांड-लाइन झंडे होते हैं जो आक्रामकता को नियंत्रित करते हैं:

  • GCC/Clang: ] मध्यम inlining सक्षम बनाता है; ] अधिक आक्रामक inlining सक्षम बनाता है। ध्वज स्पष्ट रूप से सक्षम किया जा सकता है। एक विशिष्ट समारोह को लागू करने के लिए, कम्पाइलर हेरिस्टिक्स की परवाह किए बिना, [FLT: 29]] का उपयोग या उच्चतर के साथ किया जाता है।
  • MSVC:] ]] कीवर्ड उपलब्ध है, लेकिन यह inlining की गारंटी नहीं देता है (कंपाइलर अभी भी कुछ कार्यों के लिए मना कर सकता है)।

जीसीसी विशेषता के साथ उदाहरण:

static inline __attribute__((always_inline)) int triple(int x) {
 return x * 3;
}

प्रदर्शन-महत्वपूर्ण कोड के लिए, यह सलाह दी जाती है कि उत्पन्न असेंबली (जैसे, जीसीसी के ] या ]]] के साथ यह सुनिश्चित करें कि इनलाइनिंग हुई थी। आधुनिक कम्पाइलर कार्यों को रेखांकित कर सकते हैं ]] उच्च अनुकूलन स्तर पर, और इसके विपरीत को उन कार्यों के लिए अनदेखा कर सकते हैं जो अत्यधिक कोड विकास का कारण बनेंगे।

संभावित नुकसान: कोड ब्लॉट और बाइनरी साइज

प्रत्येक कार्य के कॉल को शामिल करना जो कई स्थानों में उपयोग किया जाता है, पाठ खंड के आकार को काफी बढ़ा सकता है। यह विशेष रूप से समस्याग्रस्त है:

  • Libraries: हेडर में इनलाइन फंक्शन्स हर ट्रांसलेशन यूनिट में विस्तार होते हैं जिसमें उन्हें शामिल किया गया है, संभवतः कोड आकार को गुणा करना।
  • ]Embedded system: फ्लैश एंड रैम सीमित हैं। 1000 स्थानों में इस्तेमाल किए गए 10-byte फ़ंक्शन में लगभग 10KB कोड शामिल है।
  • ]निर्देश कैश: बड़ा कोड अधिक कैश मिस का कारण बन सकता है, पूरे कार्यक्रम को धीमा कर सकता है।

कोड ब्लोट को कम करने के लिए, केवल वास्तविक रूप से छोटे कार्यों (आमतौर पर 1-5 बयान) के लिए का उपयोग करें। अंधा-इनलाइनिंग से पहले गर्म कार्यों की पहचान करने के लिए प्रोफाइलर का उपयोग करें। दोनों निष्पादन समय और द्विआधारी आकार को मापें।

C Standards के पार इनलाइन फंक्शन

[FLT: 3]] कीवर्ड को C99] में पेश किया गया था और आगे C11]]]] और C17] में स्पष्ट किया गया था। C23 कुछ अतिरिक्त सुधारों के साथ एक ही अर्थिक अंतर को बरकरार रखता है। ऐतिहासिक अंतर "इनलाइन परिभाषा" और "बाहरी परिभाषा" के बीच भ्रम पैदा हुआ। आधुनिक अभ्यास में, अधिकांश परियोजनाएं [FLT: 39]] का उपयोग करती हैं, जो सूक्ष्मता को दर्शाता है। यह पैटर्न C99 से संबंधित सभी C मानकों के साथ काम करता है और लिंक त्रुटियों से बच जाता है।

यदि आपको प्री-C99 कम्पाइलर (जो तेजी से दुर्लभ है) का समर्थन करना होगा, तो आपको मैक्रो या बाहरी हेडर-केवल कार्यान्वयन में वापस आना चाहिए। अन्यथा, एक पोर्टेबल और टाइप-सुरक्षित विकल्प के रूप में ] को गले लगाओ।

निष्कर्ष: एक रणनीतिक उपकरण, प्रदर्शन अभियंता टूलकिट में

इनलाइन फंक्शन्स सी भाषा की एक परिपक्व, अच्छी तरह से परिभाषित विशेषता है, जब न्यायिक रूप से लागू किया जाता है, तो फंक्शन कॉल ओवरहेड को नष्ट करके और क्रॉस-फंक्शन अनुकूलन को सक्षम करके मापने योग्य गति में सुधार पैदा कर सकता है। वे लगभग हर आधुनिक संदर्भ में मैक्रो से बेहतर हैं। कुंजी उनके उपयोग को छोटे, गर्म कार्यों को सीमित करने और प्रोफाइलिंग और असेंबली निरीक्षण के साथ परिणाम को सत्यापित करने के लिए है। उपयुक्त कम्पाइलर झंडे के साथ मिलकर, इनलाइन फ़ंक्शन सी कोड को तेज और रखरखाव योग्य दोनों बनाते हैं - कम-स्तरीय प्रोग्रामिंग में एक दुर्लभ संयोजन।

आगे पढ़ने के लिए, ]GCC के इनलाइन कार्यों पर प्रलेखन और ]]]]]]]]] के लिए वास्तविक दुनिया के प्रदर्शन विश्लेषण के लिए, इस ACM Quue लेख विस्तार से व्यापार बंद की जाँच का पता लगाता है।