किसी को जवाब पता है और / या इस बारे में एक राय है?
चूंकि टुपल्स सामान्य रूप से बहुत बड़े नहीं होंगे, इसलिए मुझे लगता है कि इसके लिए कक्षाओं की तुलना में स्ट्रक्चर्स का उपयोग करना अधिक समझ में आएगा। आपने क्या कहा?
किसी को जवाब पता है और / या इस बारे में एक राय है?
चूंकि टुपल्स सामान्य रूप से बहुत बड़े नहीं होंगे, इसलिए मुझे लगता है कि इसके लिए कक्षाओं की तुलना में स्ट्रक्चर्स का उपयोग करना अधिक समझ में आएगा। आपने क्या कहा?
जवाबों:
Microsoft ने सरलता के हितों में सभी प्रकार के संदर्भ प्रकार बनाए।
मुझे व्यक्तिगत रूप से लगता है कि यह एक गलती थी। 4 से अधिक फ़ील्ड वाले ट्यूपल्स बहुत ही असामान्य हैं और उन्हें किसी भी प्रकार के अधिक वैकल्पिक विकल्प के साथ प्रतिस्थापित किया जाना चाहिए (जैसे एफ # में एक रिकॉर्ड प्रकार) इसलिए केवल छोटे ट्यूपल्स व्यावहारिक रुचि के हैं। मेरे स्वयं के बेंचमार्क ने दिखाया कि 512 बाइट्स तक अनबॉक्स किए गए ट्यूपल्स अभी भी बॉक्सिंग ट्यूपल्स की तुलना में तेज हो सकते हैं।
यद्यपि स्मृति दक्षता एक चिंता का विषय है, मेरा मानना है कि प्रमुख मुद्दा .NET गारबेज कलेक्टर का ओवरहेड है। आवंटन और संग्रह .NET पर बहुत महंगे हैं क्योंकि इसका कचरा कलेक्टर बहुत भारी रूप से अनुकूलित नहीं किया गया है (जैसे कि जेवीएम की तुलना में)। इसके अलावा, डिफ़ॉल्ट .NET GC (वर्कस्टेशन) को अभी तक समानांतर नहीं किया गया है। नतीजतन, समानांतर कार्यक्रम जो ट्यूपल्स पीस का उपयोग करते हैं, वे सभी कचरा साझा कलेक्टर के लिए प्रतिस्पर्धा करते हैं, जिससे स्केलेबिलिटी को नष्ट किया जाता है। यह न केवल प्रमुख चिंता का विषय है, बल्कि, AFAIK, Microsoft द्वारा पूरी तरह से उपेक्षित था जब उन्होंने इस समस्या की जांच की।
एक और चिंता आभासी प्रेषण है। संदर्भ प्रकार उप-प्रकारों का समर्थन करते हैं और इसलिए, उनके सदस्यों को आमतौर पर आभासी प्रेषण के माध्यम से आमंत्रित किया जाता है। इसके विपरीत, मूल्य प्रकार उप-प्रकारों का समर्थन नहीं कर सकते हैं, इसलिए सदस्य आह्वान पूरी तरह से अस्पष्ट है और हमेशा एक प्रत्यक्ष फ़ंक्शन कॉल के रूप में किया जा सकता है। वर्चुअल डिस्पैच आधुनिक हार्डवेयर पर बहुत महंगा है क्योंकि सीपीयू यह अनुमान नहीं लगा सकता है कि प्रोग्राम काउंटर कहां समाप्त होगा। वर्चुअल डिस्पैच को ऑप्टिमाइज़ करने के लिए JVM बड़ी लंबाई में जाता है लेकिन .NET ऐसा नहीं करता है। हालाँकि, .NET मान प्रकार के रूप में वर्चुअल प्रेषण से बच प्रदान करता है। इसलिए मूल्य प्रकार के रूप में ट्यूपल्स का प्रतिनिधित्व करना, फिर से, नाटकीय रूप से यहां प्रदर्शन में सुधार कर सकता है। उदाहरण के लिए, कॉलिंगGetHashCode
2-ट्यूपल पर एक लाख बार 0.17 का समय लगता है, लेकिन इसे एक समतुल्य संरचना पर कॉल करने में केवल 0.008s लगते हैं, अर्थात संदर्भ प्रकार की तुलना में मान 20 × तेज होता है।
एक वास्तविक स्थिति जहां ट्यूपल्स के साथ ये प्रदर्शन समस्याएं आमतौर पर उत्पन्न होती हैं, शब्दकोशों में कुंजियों के रूप में ट्यूपल्स के उपयोग में होती हैं। मैं वास्तव में ढेर अतिप्रवाह सवाल एफ से एक लिंक का पालन करके इस धागे पर ठोकर खाई है # पायथन की तुलना में मेरे एल्गोरिथ्म धीमी गति से चलता है! जहां लेखक का F # प्रोग्राम ठीक उसके पायथन की तुलना में धीमा निकला क्योंकि वह बॉक्सिंग ट्यूपल्स का उपयोग कर रहा था। हाथ से लिखे हुए struct
प्रकार का उपयोग करके मैन्युअल रूप से अनबॉक्सिंग करने से उसका एफ # प्रोग्राम कई बार तेज, और पायथन की तुलना में तेज हो जाता है। ये मुद्दे कभी नहीं उठते यदि ट्यूपल्स को मूल्य प्रकारों से दर्शाया जाता और न कि संदर्भ प्रकारों के साथ शुरू करने के लिए ...
Tuple<_,...,_>
प्रकारों को सील किया जा सकता था, जिस स्थिति में संदर्भ प्रकार होने के बावजूद किसी भी आभासी प्रेषण की आवश्यकता नहीं होगी। मैं इस बारे में अधिक उत्सुक हूं कि वे संदर्भ प्रकारों की तुलना में क्यों सील नहीं हैं।
कारण सबसे अधिक संभावना है क्योंकि केवल छोटे ट्यूपल्स मूल्य प्रकार के रूप में समझ में आएंगे क्योंकि उनके पास एक छोटा मेमोरी फुटप्रिंट होगा। बड़े ट्यूपल्स (यानी अधिक गुणों वाले) वास्तव में प्रदर्शन में पीड़ित होंगे क्योंकि वे 16 बाइट्स से बड़े होंगे।
इसके बजाय कुछ टुपल्स मान प्रकार के होते हैं और अन्य संदर्भ प्रकार होते हैं और डेवलपर्स को यह जानने के लिए मजबूर करते हैं कि कौन से लोग हैं जो माइक्रोसॉफ्ट पर लोगों की कल्पना करेंगे कि उन्हें सभी संदर्भ प्रकार सरल बनाने थे।
आह, संदेह की पुष्टि! कृपया बिल्डिंग टपल देखें :
पहला बड़ा निर्णय यह था कि क्या एक संदर्भ या मूल्य प्रकार के रूप में टुपल्स का इलाज किया जाए। चूँकि वे किसी भी समय अपरिवर्तनीय हैं, आप एक टुपल के मूल्यों को बदलना चाहते हैं, आपको एक नया बनाना होगा। यदि वे संदर्भ प्रकार हैं, तो इसका मतलब है कि यदि आप एक तंग लूप में एक नलिका में तत्वों को बदल रहे हैं तो बहुत अधिक कचरा उत्पन्न हो सकता है। एफ # टुपल्स संदर्भ प्रकार थे, लेकिन टीम से एक भावना थी कि वे एक प्रदर्शन में सुधार का एहसास कर सकते हैं यदि दो, और शायद तीन, तत्व ट्यूपल्स इसके बजाय मूल्य प्रकार थे। आंतरिक ट्यूपल्स बनाने वाली कुछ टीमों ने संदर्भ प्रकारों के बजाय मूल्य का उपयोग किया था, क्योंकि उनके परिदृश्य बहुत सारे प्रबंधित ऑब्जेक्ट बनाने के लिए बहुत संवेदनशील थे। उन्होंने पाया कि मूल्य प्रकार का उपयोग करने से उन्हें बेहतर प्रदर्शन मिला। टपल विनिर्देश के हमारे पहले मसौदे में, हमने शेष प्रकारों के साथ दो-, तीन- और चार-तत्व वाले ट्यूल को मूल्य प्रकार के रूप में रखा। हालांकि, एक डिज़ाइन मीटिंग के दौरान जिसमें अन्य भाषाओं के प्रतिनिधि शामिल थे, यह निर्णय लिया गया था कि यह "स्प्लिट" डिज़ाइन दोनों प्रकारों के बीच थोड़ा अलग शब्दार्थ होने के कारण भ्रमित होगा। संभावित प्रदर्शन बढ़ने की तुलना में व्यवहार और डिजाइन में स्थिरता उच्च प्राथमिकता के लिए निर्धारित की गई थी। इस इनपुट के आधार पर, हमने डिज़ाइन को बदल दिया ताकि सभी ट्यूपल्स संदर्भ प्रकार हों, हालांकि हमने एफ # टीम से यह देखने के लिए कुछ प्रदर्शन जांच करने के लिए कहा कि क्या यह ट्यूपल्स के कुछ आकारों के लिए मूल्य प्रकार का उपयोग करते समय स्पीडअप का अनुभव करता है। इसका परीक्षण करने का यह एक अच्छा तरीका था, क्योंकि इसके संकलक ने F # में लिखा था, एक बड़े कार्यक्रम का एक अच्छा उदाहरण था, जो विभिन्न प्रकार के परिदृश्यों में ट्यूपल्स का उपयोग करता था। अंत में, एफ # टीम ने पाया कि जब कुछ टुपल्स संदर्भ प्रकारों के बजाय मूल्य प्रकार थे, तो इसे प्रदर्शन में सुधार नहीं मिला। इसने हमें ट्यूपल के लिए संदर्भ प्रकारों का उपयोग करने के हमारे निर्णय के बारे में बेहतर महसूस कराया।
यदि .NET System.Tuple <...> प्रकारों को संरचना के रूप में परिभाषित किया गया था, तो वे स्केलेबल नहीं होंगे। उदाहरण के लिए, इस समय के रूप में लंबे समय के पूर्णांक का एक गुच्छेदार तराजू:
type Tuple3 = System.Tuple<int64, int64, int64>
type Tuple33 = System.Tuple<Tuple3, Tuple3, Tuple3>
sizeof<Tuple3> // Gets 4
sizeof<Tuple33> // Gets 4
यदि टर्नरी ट्यूपल को एक संरचना के रूप में परिभाषित किया गया था, तो परिणाम निम्नानुसार होगा (एक परीक्षण उदाहरण के आधार पर जो मैंने लागू किया):
sizeof<Tuple3> // Would get 32
sizeof<Tuple33> // Would get 104
जैसा कि ट्यूपल्स में F # में अंतर्निहित सिंटैक्स समर्थन है, और वे इस भाषा में बहुत बार उपयोग किए जाते हैं, "संरचना" ट्यूपल्स एफ प्रोग्रामर्स को अक्षम प्रोग्राम लिखने के जोखिम पर बताएंगे, यहां तक कि इसके बारे में पता किए बिना। यह इतनी आसानी से होगा:
let t3 = 1L, 2L, 3L
let t33 = t3, t3, t3
मेरी राय में, "संरचना" ट्यूपल्स रोज़मर्रा की प्रोग्रामिंग में महत्वपूर्ण अक्षमता पैदा करने की एक उच्च संभावना का कारण होगा। दूसरी ओर, वर्तमान में "क्लास" ट्यूपल भी कुछ अक्षमताओं का कारण बनते हैं, जैसा कि @Jon द्वारा उल्लेख किया गया है। हालांकि, मुझे लगता है कि "होने की संभावना" समय "संभावित क्षति" का उत्पाद वर्तमान में कक्षाओं के साथ तुलना में बहुत अधिक होगा। इसलिए, वर्तमान कार्यान्वयन कम बुराई है।
आदर्श रूप से, F # में दोनों सिंटैक्टिक सपोर्ट के साथ "क्लास" टुपल्स और "स्ट्रक्चर" टुपल्स दोनों होंगे!
संपादित करें (2017-10-07)
संरचना टुपल्स अब पूरी तरह से इस प्रकार समर्थित हैं:
ref
, या इस तथ्य को पसंद नहीं कर सकता है कि तथाकथित "अपरिवर्तनीय स्ट्रक्चर्स" नहीं हैं, खासकर जब बॉक्सिंग। यह बहुत बुरा है। किसी भी लागू करने वाले मापदंडों की अवधारणा को कभी भी लागू नहीं किया जाता है const ref
, क्योंकि कई मामलों में ऐसे शब्दार्थ हैं जो वास्तव में आवश्यक हैं।
Dictionary
, जैसे कि यहां: stackoverflow.com/estestions/5850243 /…
2-ट्यूपल के लिए, आप अभी भी कॉमन टाइप सिस्टम के पुराने संस्करणों से हमेशा KeyValuePair <TKey, TValue> का उपयोग कर सकते हैं। यह एक मूल्य प्रकार है।
मैट एलिस लेख के लिए एक मामूली स्पष्टीकरण यह होगा कि संदर्भ और मूल्य प्रकारों के बीच शब्दार्थ का उपयोग करने में अंतर केवल "मामूली" होता है जब अपरिवर्तनीयता प्रभाव में होती है (जो निश्चित रूप से, यहां मामला होगा)। फिर भी, मुझे लगता है कि बीसीएल डिजाइन में यह सबसे अच्छा रहा होगा कि कुछ सीमा पर टुपल क्रॉस को एक संदर्भ प्रकार पर रखने का भ्रम न हो।
मुझे नहीं पता लेकिन अगर आपने कभी F # Tuples का इस्तेमाल किया है तो वह भाषा का हिस्सा है। अगर मैंने एक .dll बनाया और एक प्रकार का टुल्ल्स लौटाया, तो उस प्रकार का टाइप करना अच्छा होगा, मुझे अब संदेह है कि F # भाषा का हिस्सा है (.Net 4) कुछ सामान्य संरचनाओं को समायोजित करने के लिए CLR में कुछ संशोधन किए गए थे। F # में
से http://en.wikibooks.org/wiki/F_Sharp_Programming/Tuples_and_Records
let scalarMultiply (s : float) (a, b, c) = (a * s, b * s, c * s);;
val scalarMultiply : float -> float * float * float -> float * float * float
scalarMultiply 5.0 (6.0, 10.0, 20.0);;
val it : float * float * float = (30.0, 50.0, 100.0)
ValueTuple<...>
। C # tuple प्रकार