2009-06-11 13 views
56

मैं केवल उद्देश्य सी (खिलौना आईफोन ऐप्स लिखना) के साथ खेलने के लिए घूर रहा हूं और मैं संदेशों को प्रेषित करने के लिए उपयोग की जाने वाली अंतर्निहित तंत्र के बारे में उत्सुक हूं। मुझे अच्छी समझ है कि सी ++ में वर्चुअल फ़ंक्शंस को आम तौर पर कार्यान्वित किया जाता है और लागत स्थिर या गैर वर्चुअल विधि कॉल के सापेक्ष क्या होती है, लेकिन मेरे पास ओब्जे-सी के साथ कोई पृष्ठभूमि नहीं है यह जानने के लिए कि संदेश कैसे भेजे जाते हैं। मुझे आसपास के ब्राउज़िंग में this ढीला बेंचमार्क मिला और यह आईएमपी कैश किए गए संदेशों को आभासी फ़ंक्शन कॉल से तेज़ होने का उल्लेख करता है, जो एक मानक संदेश भेजने की तुलना में तेज़ी से बदलते हैं।उद्देश्य सी संदेश प्रेषण तंत्र

मैं कुछ भी अनुकूलित करने की कोशिश नहीं कर रहा हूं, बस संदेशों को प्रेषित करने के बारे में गहरी समझ प्राप्त करें।

  • ओबीजे-सी संदेश कैसे प्रेषित किए जाते हैं?
  • इंस्टेंस विधि पॉइंटर्स कैश कैसे प्राप्त करते हैं और क्या आप (सामान्य रूप से) कोड पढ़कर बता सकते हैं कि कोई संदेश कैश हो जाएगा?
  • क्या क्लास विधियां अनिवार्य रूप से सी फ़ंक्शन (या सी ++ में स्थिर वर्ग विधि) जैसी हैं, या क्या उनके लिए कुछ और है?

मुझे पता है कि इनमें से कुछ प्रश्न 'कार्यान्वयन निर्भर' हो सकते हैं लेकिन वास्तव में केवल एक ही कार्यान्वयन है जो वास्तव में मायने रखता है।

उत्तर

83

ओबीजे-सी संदेश कैसे प्रेषित किए जाते हैं?

उद्देश्य-सी संदेश रनटाइम के objc_msgSend() फ़ंक्शन का उपयोग करके प्रेषित किए जाते हैं। [। संदेश पर तर्कों की एक चर सूची भेजी जा रही]

  1. प्राप्त वस्तु
  2. संदेश के चयनकर्ता
: Apple docs में दिखाया गया है, समारोह कम से कम 2 तर्क लेता है

कक्षा के उदाहरणों में isa पॉइंटर है, जो कि उनके क्लास ऑब्जेक्ट के लिए पॉइंटर है। प्रत्येक ऑब्जेक्ट में विधियों के चयनकर्ता वर्ग ऑब्जेक्ट में "टेबल" में संग्रहीत होते हैं, और objc_msgSend() फ़ंक्शन क्लास ऑब्जेक्ट में isa पॉइंटर का पालन करता है, इस तालिका को खोजने के लिए, और यह जांचता है कि विधि कक्षा के लिए तालिका में है या नहीं । यदि यह नहीं मिल रहा है, तो यह कक्षा के सुपरक्लास की तालिका में विधि की तलाश करता है। यदि नहीं मिला, तो यह ऑब्जेक्ट ट्री जारी रखता है, जब तक कि यह या तो विधि पाता है या रूट ऑब्जेक्ट (NSObject) तक पहुंच जाता है। इस बिंदु पर, एक अपवाद फेंक दिया जाता है।

इंस्टेंस विधि पॉइंटर्स कैश कैसे होते हैं और क्या आप (सामान्य रूप से) कोड को पढ़कर बता सकते हैं कि कोई संदेश कैश किया जाएगा?

एप्पल के ऑब्जेक्टिव-सी क्रम गाइड से Messaging पर:

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

जैसा कि कहा गया है, कार्यक्रम चलने के बाद कैशिंग शुरू हो जाती है, और कार्यक्रम के लंबे समय तक चलने के बाद, अधिकांश विधि कॉल कैश्ड विधि के माध्यम से चलेंगे। जैसा कि यह भी कहता है, कैशिंग होती है क्योंकि विधियों का उपयोग किया जाता है, इसलिए जब इसका उपयोग किया जाता है तो एक संदेश केवल कैश किया जाता है।

क्या क्लास विधियां अनिवार्य रूप से सी फ़ंक्शन (या सी ++ में स्थिर वर्ग विधि) जैसी हैं, या क्या उनके लिए कुछ और है?

कक्षा वस्तुओं कक्षाओं के उदाहरणों के समान तरीके से विधि प्रेषण संभालती है। प्रत्येक वर्ग ऑब्जेक्ट में एक ऑब्जेक्ट होता है जो नामक ऑब्जेक्ट में अपने वर्ग विधियों को संग्रहीत करता है। क्लास ऑब्जेक्ट का अपना isa पॉइंटर है जो इसके मेटाक्लास ऑब्जेक्ट में है, जिसके बदले में सुपर मेटाक्लास ऑब्जेक्ट्स हैं, जो क्लास ऑब्जेक्ट्स को प्राप्त कर सकते हैं। वर्ग तरीकों की विधि प्रेषण के रूप में तो यह है:

  1. प्रेषण प्रणाली metaclass वस्तु
  2. metaclass वस्तु की विधि तालिका वर्ग विधि की खोज की है करने के लिए वर्ग वस्तु की isa सूचक इस प्रकार है।
  3. यदि नहीं मिला, तो खोज मेटाक्लास ऑब्जेक्ट के सुपरक्लास पर जारी है, जहां खोज जारी है।
  4. यह प्रक्रिया तब तक दोहराई जाती है जब तक कि विधि पाई जाती है, या जब तक यह रूट मेटाक्लास नहीं हो जाती है, और अपवाद फेंक दिया जाता है।
+7

बहुत बढ़िया विवरण। मुझे लगता है कि गतिशील प्रेषण प्रणाली को समझना और चयनकर्ता कैसे शामिल हैं, यह भी बताते हैं कि विधि नाम अद्वितीय क्यों होना चाहिए, और उद्देश्य-सी जावा और सी ++ के समान तरीके से ओवरलोडेड विधियों का समर्थन नहीं करता है। चूंकि चयनकर्ता को पूर्णांक के रूप में कैश किया जाता है, उसी नाम वाला कोई भी विधि उसी चयनकर्ता को मैप करेगा। बेहतर या बदतर के लिए, यह प्रोग्राम्स को उचित तरीके से नामकरण विधियों के बारे में अधिक सोचने के लिए मजबूर करता है। –

+4

यदि आप गहरे जाना चाहते हैं ... http://www.friday.com/bbum/2009/12/18/objc_msgsend-part-1-the-road-map/ – bbum

+1

विशेष 'आगे' और ' performv 'तरीकों? उन्हें कब बुलाया जाता है? –

19

मैं भी objc_msgSend के लिए अनुदेश गाइड() द्वारा एक निर्देश x86_64 पर मेरी वेबलॉग पर लिखा है, तो किसी को भी गहरा गोता करना चाहता है:

http://www.friday.com/bbum/2009/12/18/objc_msgsend-part-1-the-road-map/

+3

ग्रेट आलेख! +1 – jweyrich

+1

दिलचस्प पढ़ा। "ध्यान दें कि चयनकर्ता एक सी स्ट्रिंग है, लेकिन चयनकर्ता भी अनन्य हैं, इस प्रकार कैश लुकअप को केवल स्ट्रिंग पते की तुलना करने की इजाजत देता है।" मुझे यह एक ही प्रक्रिया में मिलता है, लेकिन यह मॉड्यूल सीमाओं में कैसे पूरा किया जाता है? –

+2

@DwayneRobinson एक निष्पादन योग्य लोड के रूप में डाइल्ड द्वारा निष्पादित एक 'फिक्सअप' चरण है जो ऐसे सभी सामान्य डेटा को हल और सामान्य करता है। मुझे ब्योरा याद नहीं है और, स्पष्ट रूप से, मैंने आखिरी बार देखा क्योंकि वे शायद बदल गए हैं। रनटाइम और डाइल्ड का स्रोत यहां उपलब्ध है http://www.opensource.apple.com। दिलचस्प पढ़ता है। – bbum

संबंधित मुद्दे