मैं एक स्थिर कलाकार की तरह जबरदस्ती हासिल करने की कोशिश कर रहा हूं जिसके परिणामस्वरूप किसी भी डेटा की नकल नहीं होती है। एक भोली स्थिर कलाकार काम नहीं करता है

let pkt = byte_buffer :> PktHeader

FS0193: प्रकार बाधा बेमेल। प्रकार बाइट [] प्रकार के साथ संगत नहीं है PktHeader प्रकार 'बाइट []' प्रकार 'PktHeader' (FS0193) (कार्यक्रम) के साथ संगत नहीं है

जहां पैकेट को शुरू में बाइट सरणी में रखा गया है, क्योंकि System.Net.Sockets.Socket.Receive () को परिभाषित किया गया है। निम्न स्तर के पैकेट संरचना को कुछ इस तरह परिभाषित किया गया है

[<Struct; StructLayout(LayoutKind.Explicit)>]
type PktHeader =
  [<FieldOffset(0)>] val mutable field1: uint16
  [<FieldOffset(2)>] val mutable field2: uint16
  [<FieldOffset(4)>] val mutable field3: uint32
   .... many more fields follow ....

इस वास्तविक दुनिया के परिदृश्य में दक्षता महत्वपूर्ण है क्योंकि डेटा की बेकार नकल एक कार्यान्वयन भाषा के रूप में एफ # बाहर शासन कर सकती है। आप इस परिदृश्य में शून्य प्रतिलिपि क्षमता कैसे प्राप्त करते हैं?

ईडीआईटी 29 नवंबर को मेरा सवाल निहित विश्वास पर समर्पित था कि एक सी / सी ++ / सी # शैली असुरक्षित स्थिर डाली एक उपयोगी निर्माण है, जैसे कि यह स्वयं स्पष्ट है। हालांकि, 2 पर लगा कि इस तरह की कास्ट F # में मुहावरेदार नहीं है क्योंकि यह स्वाभाविक रूप से एक अनिवार्य भाषा तकनीक है जो संकट से घिरी हुई है। इस कारण मैंने V.B. द्वारा उत्तर स्वीकार कर लिया है। जहाँ SBE / FlatBuffers डेटा का उपयोग सर्वोत्तम अभ्यास के रूप में किया जाता है।

f#
5
user4434256 26 नवम्बर 2015, 16:59

2 जवाब

सबसे बढ़िया उत्तर

F # और बहुत कम-स्तरीय प्रदर्शन अनुकूलन सबसे अच्छे दोस्त नहीं हैं, लेकिन फिर ... कुछ स्मार्ट लोग जावा के साथ भी जादू करते हैं, जिसमें उनके लिए मूल्य प्रकार और वास्तविक सामान्य संग्रह नहीं हैं।

1) मैं हाल ही में एक फ्लाईवेट पैटर्न का बहुत बड़ा प्रशंसक हूं। यदि आप वास्तुकला इसके लिए अनुमति देते हैं, तो आप एक बाइट सरणी और ऑफ़सेट के माध्यम से संरचना सदस्यों तक पहुंच सकते हैं। AC # उदाहरण यहां । SBE / FlatBuffers भी एक परिभाषा से स्वचालित रूप से एक आवरण उत्पन्न करने के लिए उपकरण है।

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

3) तीसरा विकल्प .NET प्रकार की प्रणाली का दुरुपयोग कर रहा है और IL के साथ एक बाइट सरणी दे रहा है जैसे यह (इसमें कोड किया जा सकता है एफ #, अगर आप जोर देते हैं :)):

static T UnsafeCast(object value) {
 ldarg.1 //load type object
 ret //return type T
}

मैंने इस विकल्प की कोशिश की और यहां तक कि अगर आपको ज़रूरत है तो एक स्निपेट भी है, लेकिन यह दृष्टिकोण मुझे असहज बनाता है क्योंकि मैं जीसी के लिए इसके परिणामों को नहीं समझता हूं। हमारे पास एक ही मेमोरी द्वारा समर्थित दो ऑब्जेक्ट हैं, उनमें से एक GCed होने पर क्या होगा? मैं इस विवरण के बारे में SO पर एक नया प्रश्न पूछने जा रहा था, जल्द ही इसे पोस्ट करूंगा।


अंतिम दृष्टिकोण संरचनाओं के सरणियों के लिए अच्छा हो सकता है, लेकिन एक एकल संरचना के लिए यह इसे बॉक्स करेगा या वैसे भी कॉपी करेगा। चूँकि स्ट्रक्चर्स स्टैक पर हैं और वैल्यू द्वारा पास किए गए हैं, आप शायद असुरक्षित सी # में एक पॉइंटर को कास्टिंग करके या दूसरे उत्तर में {{एक्स 1}} का उपयोग करके बेहतर परिणाम प्राप्त करेंगे, और फिर वैल्यू द्वारा कॉपी करें। नकल करना सबसे बुरी बात नहीं है, विशेष रूप से स्टैक पर, लेकिन नई वस्तुओं का आवंटन और जीसी दुश्मन है, इसलिए आपको बाइटेड ऐरे की आवश्यकता है और यह आपके द्वारा कॉम्पेक्ट कास्टिंग मुद्दे की तुलना में समग्र प्रदर्शन में बहुत अधिक जोड़ देगा।

लेकिन यदि आपकी संरचना बहुत बड़ी है, तो विकल्प 1 अभी भी बेहतर हो सकता है।

0
Community 23 मई 2017, 12:30

रूपांतरण के लिए एक शुद्ध एफ # दृष्टिकोण

let convertByteArrayToStruct<'a when 'a : struct> (byteArr : byte[]) = 
    let handle = GCHandle.Alloc(byteArr, GCHandleType.Pinned)
    let structure = Marshal.PtrToStructure (handle.AddrOfPinnedObject(), typeof<'a>)
    handle.Free()
    structure :?> 'a

यह एक न्यूनतम उदाहरण है, लेकिन मैं बाइट सरणी की लंबाई पर कुछ जांच शुरू करने की सलाह दूंगा, क्योंकि जैसा कि वहां लिखा गया है, यदि आप इसे बाइट सरणी देते हैं तो यह अपरिभाषित परिणाम देगा। आप Marshall.SizeOf(typeof<'a>) के खिलाफ जांच कर सकते हैं।


इस से कम सुरक्षित रूपांतरण करने के लिए कोई शुद्ध एफ # समाधान नहीं है (और यह पहले से ही रनटाइम विफलता का एक दृष्टिकोण है)। वैकल्पिक विकल्प रूपांतरण को करने के लिए unsafe और fixed का उपयोग करने के लिए C # के साथ इंटरोप को शामिल कर सकते हैं।

अंतत:, आप F # प्रकार प्रणाली को हटाने के लिए रास्ता पूछ रहे हैं जो वास्तव में भाषा के लिए डिज़ाइन नहीं किया गया है। एफ # के सिद्धांत लाभों में से एक प्रकार की प्रणाली की शक्ति है और यह आपको सांख्यिकीय रूप से सत्यापन योग्य कोड बनाने में मदद करने की क्षमता है।

2
TheInnerLight 27 नवम्बर 2015, 17:54