2009-05-31 20 views
23

और अधिक कुशल क्या है मैं यहां टोकनेज़र के बारे में सोच रहा हूं।
प्रत्येक टोकन पार्सर के अंदर एक अलग फ़ंक्शन कॉल करता है।
क्या और अधिक कुशल है:एक स्विच केस या std :: मैप

  • std :: कार्यों का एक नक्शा/बढ़ावा देने :: कार्यों
  • एक स्विच मामले

उत्तर

17

एसटीएल मानचित्र कि विजुअल स्टूडियो 2008 के साथ आता है आप दे देंगे ओ (लॉग (एन)) प्रत्येक फंक्शन कॉल के लिए क्योंकि यह नीचे एक वृक्ष संरचना छुपाता है। आधुनिक कंपाइलर (कार्यान्वयन के आधार पर) के साथ, एक स्विच स्टेटमेंट आपको ओ (1) देगा, संकलक इसे किसी प्रकार की लुकअप टेबल में अनुवाद करता है। तो सामान्य रूप से, स्विच तेज़ होता है।

हालांकि, निम्न तथ्यों पर विचार करें:

मानचित्र और स्विच के बीच अंतर यह है कि है: मानचित्र गतिशील परिवर्तन नहीं कर सकते, जबकि बनाया जा सकता है। मानचित्र में कुंजी के रूप में कोई मनमाना प्रकार हो सकता है जबकि स्विच सी ++ आदिम प्रकारों (char, int, enum, आदि ...) तक बहुत सीमित है।

वैसे, आप लगभग ओ (1) प्रेषण प्राप्त करने के लिए हैश मानचित्र का उपयोग कर सकते हैं (हालांकि, हैश तालिका कार्यान्वयन के आधार पर, यह कभी-कभी सबसे खराब स्थिति में ओ (एन) हो सकता है)। हालांकि, स्विच अभी भी तेज होगा।

संपादित

मैं लिख रहा हूँ निम्नलिखित केवल मनोरंजन के लिए और चर्चा की बात के लिए

मैं तुम्हारे लिए एक अच्छा अनुकूलन कर सकते हैं सुझाव है, लेकिन यह अपनी भाषा की प्रकृति पर निर्भर करता है और चाहे आप उम्मीद कर सकें कि आपकी भाषा का उपयोग कैसे किया जाएगा।

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

विचार सीपीयू शाखा भविष्यवाणी का उपयोग करना है ताकि किसी भी स्तर के संकेत से बचने के लिए (अगर कथन में स्थिति जांच लगभग बेकार है)। अधिकांश मामलों में सीपीयू किसी भी स्तर के संकेत के बिना सही शाखा लेगा। वे कुछ मामले होंगे हालांकि शाखा गलत जगह पर जाएगी। आपके लैंग्यूज की प्रकृति के आधार पर, सांख्यिकीय रूप से यह बेहतर प्रदर्शन दे सकता है।

संपादित करें: नीचे दी गई कुछ टिप्पणियों के कारण, परिवर्तित वाक्य यह बताता है कि कंपाइलर्स हमेशा एलयूटी पर स्विच का अनुवाद करेंगे।

+5

संकलक इसे एक लुकअप टेबल में परिवर्तित कर सकता है, लेकिन ऐसा करने की कोई आवश्यकता नहीं है। यदि ऐसा नहीं होता है, तो यह ओ (एन) होगा। –

+0

मैंने देखा है कि सभी पार्सर्स एक स्विच केस का उपयोग करें। क्या इसके लिए कोई अच्छा कारण है? –

+2

जैसे yossi1981 ने कहा, ज्यादातर मामलों में एक स्विच स्टेटमेंट बहुत तेज है। इसलिए यदि आपके पास विकल्प है (आमतौर पर पार्सर्स (या टोकननाइज़र/लेक्सर की अधिक संभावना) एक विशिष्ट वाक्यविन्यास का पालन करें, रनटाइम में नहीं बनाया गया है) तो आपको एक स्विच पसंद करना चाहिए। –

3

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

1

आप यह नहीं कहते कि आपके टोकन किस प्रकार हैं। अगर वे पूर्णांक नहीं हैं, तो आपके पास कोई विकल्प नहीं है - स्विच केवल पूर्णांक प्रकारों के साथ काम करते हैं।

+0

वे एक enum –

2

जैसा कि yossi1981 ने कहा था, एक स्विच को तेजी से लुकअप-टेबल की मधुमक्खी का अनुकूलन किया जा सकता है लेकिन गारंटी नहीं है, प्रत्येक कंपाइलर के पास यह निर्धारित करने के लिए अन्य एल्गोरिदम हैं कि स्विच को लगातार लागू करने के लिए या तेज लुकअप टेबल के रूप में, या शायद दोनों का संयोजन।

एक तेज स्विच प्राप्त करने के लिए आपके मूल्यों को निम्नलिखित नियमों को पूरा करना चाहिए: वे लगातार होना चाहिए, उदाहरण के लिए 0,1,2,3,4। आप कुछ मूल्यों को छोड़ सकते हैं लेकिन 0,1,2,34,43 जैसी चीजें अनुकूलित होने की संभावना नहीं है।

प्रश्न वास्तव में है: क्या आपके आवेदन में इस तरह के महत्व का प्रदर्शन है? और कोई नक्शा जो फ़ाइल से गतिशील रूप से अपने मूल्यों को लोड नहीं करता है, वह एक विशाल कथन के बजाय अधिक पठनीय और रखरखाव योग्य होगा जो कोड के कई पृष्ठों को फैलाता है?

+0

हां यह है। यह एक पटकथा भाषा है। –

0

सी ++ मानक इसकी आवश्यकताओं के प्रदर्शन के बारे में कुछ भी नहीं कहता है, केवल कार्यक्षमता वहां होना चाहिए।

इस प्रकार के प्रश्न बेहतर या तेज़ या अधिक कुशल हैं जब तक कि आप बताते हैं कि कार्यान्वयन आप किस बारे में बात कर रहे हैं। उदाहरण के लिए, जावास्क्रिप्ट के एक निश्चित कार्यान्वयन के एक निश्चित संस्करण में स्ट्रिंग हैंडलिंग अत्याचारी थी, लेकिन आप प्रासंगिक मानक की सुविधा के लिए इसे extrapolate नहीं कर सकते हैं।

मैं अब तक कहूंगा कि यह कार्यान्वयन के बावजूद कोई फर्क नहीं पड़ता क्योंकि switch और std::map द्वारा प्रदान की गई कार्यक्षमता अलग है (हालांकि ओवरलैप है)।

मेरी राय में माइक्रो-ऑप्टिमाइज़ेशन इस तरह के आवश्यक नहीं हैं।

25

मैं सॉफ़्टवेयर पर जोएल से switch() vs. lookup table? पढ़ने का सुझाव दूंगा। विशेष रूप से, इस प्रतिक्रिया दिलचस्प है:

"। समय बर्बाद कर कम से कम महत्वपूर्ण बात का अनुकूलन करने की कोशिश कर लोगों के प्रधान उदाहरण"

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

आभासी मशीनों में, कॉल करने के लिए गणना किए गए पते को संग्रहीत लुकअप टेबल आमतौर पर स्विच करने के लिए प्राथमिकता दी जाती है। (प्रत्यक्ष थ्रेडिंग, या "मान के रूप में लेबल"। सीधे लुकअप टेबल में संग्रहीत लेबल पता को कॉल करता है) ऐसा इसलिए है क्योंकि यह branch misprediction को कम करने के लिए कुछ शर्तों के तहत अनुमति देता है, जो लंबे समय तक पाइपलाइन सीपीयू में बेहद महंगा है (यह फ्लश करने के लिए मजबूर करता है पाइप लाइन)। हालांकि, कोड कम पोर्टेबल बनाता है।

इस मुद्दे पर वीएम समुदाय में व्यापक रूप से चर्चा की गई है, तो मैं आपको इस क्षेत्र में विद्वानों के कागजात देखने के लिए सुझाव दूंगा यदि आप इसके बारे में अधिक पढ़ना चाहते हैं।एर्टेल & ग्रेग, 2001 में इस विषय पर एक महान लेख लिखा था The Behavior of Efficient Virtual Machine Interpreters on Modern Architectures

लेकिन के रूप में उल्लेख, मैं बहुत यकीन है कि इन विवरणों अपने कोड के लिए प्रासंगिक नहीं हैं हूँ। ये छोटे विवरण हैं, और आपको इस पर अधिक ध्यान केंद्रित नहीं करना चाहिए। पायथन दुभाषिया स्विच का उपयोग कर रहा है, क्योंकि उन्हें लगता है कि यह कोड को और अधिक पठनीय बनाता है। आप उस उपयोग को क्यों नहीं चुनते हैं जिसके साथ आप सबसे सहज हैं? प्रदर्शन प्रभाव अपेक्षाकृत छोटे हो जाएगा, तो आप बेहतर अब के लिए कोड पठनीयता पर ध्यान केंद्रित करता हूँ;)

संपादित: अगर यह मायने रखता है, एक हैश तालिका का उपयोग कर हमेशा एक लुकअप तालिका की तुलना में धीमी हो जाएगा। लुकअप टेबल के लिए, आप अपनी "कुंजी" के लिए enum प्रकार का उपयोग करते हैं, और एक अप्रत्यक्ष कूद का उपयोग करके मान पुनर्प्राप्त किया जाता है। यह एक एकल असेंबली ऑपरेशन है। हे (1)। एक हैश टेबल लुकअप को पहले हैश की गणना करने की आवश्यकता होती है, फिर मूल्य को पुनर्प्राप्त करने के लिए, जो कि अधिक महंगा है।

फ़ंक्शन पते संग्रहीत किए जाने वाले सरणी का उपयोग करके, और enum के मानों का उपयोग करके एक्सेस किया जाता है। लेकिन एक हैश तालिका का उपयोग कर भी ऐसा ही करने के लिए एक महत्वपूर्ण भूमि के ऊपर

सारांश में कहते हैं, हमने:

  • लागत (Hash_table) >> लागत (direct_lookup_table)
  • लागत (direct_lookup_table) ~ = लागत (स्विच) यदि आपका कंपाइलर अनुवाद लुकअप टेबल में स्विच करता है।
  • लागत (स्विच) >> लागत (direct_lookup_table) (ओ (एन) बनाम ओ (1)) यदि आपका कंपाइलर स्विच का अनुवाद नहीं करता है और सशर्त का उपयोग नहीं करता है, लेकिन मैं ऐसा करने वाले किसी भी कंपाइलर के बारे में नहीं सोच सकता।
  • लेकिन रेखांकित प्रत्यक्ष थ्रेडिंग कोड को कम पठनीय बनाता है।
+1

ग्रेट उत्तर। मैं आज के लिए उपरोक्त से बाहर हूं। :) टॉमोरो आपको एक मिल जाएगा। –

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