में मैं एक ऐसी स्थिति में आया जहां मेरे पास एक बहुत बड़ी फ़ाइल है जिसे मुझे बाइनरी डेटा पढ़ने की आवश्यकता है।तेज (असुरक्षित) BETReader .NET
नतीजतन, मुझे एहसास हुआ कि .NET में डिफ़ॉल्ट बाइनरी रीडर कार्यान्वयन बहुत धीमा है। .NET Reflector साथ इसे देख करने पर मैं इस भर में आया था:
public virtual int ReadInt32()
{
if (this.m_isMemoryStream)
{
MemoryStream stream = this.m_stream as MemoryStream;
return stream.InternalReadInt32();
}
this.FillBuffer(4);
return (((this.m_buffer[0] | (this.m_buffer[1] << 8)) | (this.m_buffer[2] << 0x10)) | (this.m_buffer[3] << 0x18));
}
कौन सा मुझे अत्यंत अक्षम हमलों, कैसे कंप्यूटर 32 बिट मूल्यों के साथ काम करने के लिए के बाद से 32 बिट सीपीयू आविष्कार किया गया था डिजाइन किए गए थे पर सोच।
तो मैं इस तरह के बजाय के रूप में अपने खुद के (असुरक्षित) FastBinaryReader कोड के साथ वर्ग बनाया:
public unsafe class FastBinaryReader :IDisposable
{
private static byte[] buffer = new byte[50];
//private Stream baseStream;
public Stream BaseStream { get; private set; }
public FastBinaryReader(Stream input)
{
BaseStream = input;
}
public int ReadInt32()
{
BaseStream.Read(buffer, 0, 4);
fixed (byte* numRef = &(buffer[0]))
{
return *(((int*)numRef));
}
}
...
}
कौन सा बहुत तेजी से है - मैं समय 5-7 सेकंड बंद दाढ़ी बनाने के लिए प्रबंधित यह एक पढ़ने के लिए ले लिया 500 एमबी फ़ाइल, लेकिन यह अभी भी काफी धीमी है (शुरुआत में 2 9 सेकंड और मेरे FastBinaryReader
के साथ ~ 22 सेकंड)।
यह अभी भी मुझे परेशान करता है कि यह अपेक्षाकृत छोटी फ़ाइल को पढ़ने के लिए इतना लंबा क्यों लगता है। अगर मैं फ़ाइल को एक डिस्क से दूसरी डिस्क में कॉपी करता हूं तो इसमें केवल कुछ सेकंड लगते हैं, इसलिए डिस्क थ्रूपुट कोई समस्या नहीं है।
मैं आगे ReadInt32 inlined, आदि कॉल, और मैं इस कोड के साथ समाप्त हो गया:
using (var br = new FastBinaryReader(new FileStream(cacheFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, 0x10000, FileOptions.SequentialScan)))
while (br.BaseStream.Position < br.BaseStream.Length)
{
var doc = DocumentData.Deserialize(br);
docData[doc.InternalId] = doc;
}
}
public static DocumentData Deserialize(FastBinaryReader reader)
{
byte[] buffer = new byte[4 + 4 + 8 + 4 + 4 + 1 + 4];
reader.BaseStream.Read(buffer, 0, buffer.Length);
DocumentData data = new DocumentData();
fixed (byte* numRef = &(buffer[0]))
{
data.InternalId = *((int*)&(numRef[0]));
data.b = *((int*)&(numRef[4]));
data.c = *((long*)&(numRef[8]));
data.d = *((float*)&(numRef[16]));
data.e = *((float*)&(numRef[20]));
data.f = numRef[24];
data.g = *((int*)&(numRef[25]));
}
return data;
}
यह कैसे भी तेजी से बनाने के लिए पर किसी भी आगे विचार? मैं सोच रहा था कि मैं कुछ कस्टम संरचना के शीर्ष पर पूरी फ़ाइल को सीधे स्मृति में मैप करने के लिए मार्शलिंग का उपयोग कर सकता हूं, क्योंकि डेटा रैखिक, निश्चित आकार और अनुक्रमिक है।
सॉल्व: मैं इस निष्कर्ष पर पहुंचा कि फाइलस्ट्रीम के बफरिंग/बुफर्डस्ट्रीम त्रुटिपूर्ण हैं। कृपया स्वीकार किए गए उत्तर और मेरे स्वयं के उत्तर (समाधान के साथ) देखें।
यह सहायक हो सकता है: http://stackoverflow.com/questions/19558435/what-is-the-best-buffer-size-when-using-binaryreader-to-read-big-files-1gb/19837238? noredirect = 1 # 19837238 –