शौक़ीन बनाम असंबद्ध IO


84

मुझे पता चला कि कार्यक्रमों में डिफ़ॉल्ट रूप से I / O बफर किया जाता है, अर्थात उन्हें अस्थायी स्टोरेज से अनुरोध करने वाले प्रोग्राम में परोसा जाता है। मैं समझता हूं कि बफरिंग आईओ प्रदर्शन (शायद सिस्टम कॉल को कम करके) में सुधार करता है। मैंने बफरिंग को अक्षम करने के उदाहरण देखे हैं, जैसे setvbufसी। में दो मोड के बीच अंतर क्या है और एक को दूसरे पर कब इस्तेमाल किया जाना चाहिए?

जवाबों:


127

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

एक अन्य उदाहरण एक लॉगिंग लाइब्रेरी है। यदि आपकी प्रक्रिया में आपके लॉग संदेश बफ़र के भीतर आयोजित किए जाते हैं, और आपकी प्रक्रिया कोर खोदती है, तो एक बहुत अच्छा मौका है कि आउटपुट कभी नहीं लिखा जाएगा।

इसके अलावा, यह सिर्फ सिस्टम कॉल नहीं है जो कम से कम हो, बल्कि डिस्क I / O भी हो। मान लीजिए कि एक प्रोग्राम एक बार में एक फाइल बाइट पढ़ता है। असंबद्ध इनपुट के साथ, आप हर बाइट के लिए (अपेक्षाकृत बहुत धीमी) डिस्क के लिए बाहर निकल जाएंगे, भले ही इसे संभवतः पूरे ब्लॉक में पढ़ना होगा (डिस्क हार्डवेयर में स्वयं बफ़र्स हो सकते हैं लेकिन आप अभी भी डिस्क नियंत्रक के लिए जा रहे हैं जो इन-मेमोरी एक्सेस की तुलना में धीमा होने वाला है)।

बफरिंग करके, पूरे ब्लॉक को एक बार बफर में पढ़ा जाता है फिर व्यक्तिगत बाइट्स को (इन-मेमोरी, अविश्वसनीय रूप से तेज) बफर क्षेत्र से आप तक पहुंचाया जाता है।

ध्यान रखें कि बफरिंग कई रूप ले सकती है, जैसे कि निम्न उदाहरण में:

+-------------------+-------------------+
| Process A         | Process B         |
+-------------------+-------------------+
| C runtime library | C runtime library | C RTL buffers
+-------------------+-------------------+
|               OS caches               | Operating system buffers
+---------------------------------------+
|      Disk controller hardware cache   | Disk hardware buffers
+---------------------------------------+
|                   Disk                |
+---------------------------------------+

ग्राफ अद्भुत है। उल्लेख के लायक एक बात यह है कि एक FILEवस्तु (एक धारा) आंतरिक रूप से बफर एक fgetsआवश्यक बफर पैरामीटर से पूरी तरह से अलग है । इससे पहले कि मैं यह पता लगाने के लिए कुछ कोड लिखता उससे पहले ही मुझे घंटों के लिए भ्रमित कर दिया। QAQ
रिक

37

जब आप पहले से ही डिस्क पर लिखने के लिए तैयार बाइट्स का बड़ा क्रम रखते हैं, तो आप असंबद्ध आउटपुट चाहते हैं, और बीच में दूसरी बफर में एक अतिरिक्त प्रतिलिपि से बचना चाहते हैं ।

बफ़र किए गए आउटपुट स्ट्रीम एक मध्यवर्ती बफर में लिखने के परिणाम जमा करेंगे, इसे केवल तभी ओएस फाइल सिस्टम में भेजा जाएगा जब पर्याप्त डेटा जमा हो गया है (या flush()अनुरोध किया गया है)। यह फ़ाइल सिस्टम कॉल की संख्या को कम करता है। चूँकि फ़ाइल सिस्टम कॉल अधिकांश प्लेटफ़ॉर्म (लघु की तुलना में memcpy) पर महंगी हो सकती हैं , बफ़र आउटपुट बड़ी संख्या में छोटे लेखन करते समय एक शुद्ध जीत है। असंबद्ध आउटपुट आम तौर पर तब बेहतर होता है जब आपके पास भेजने के लिए पहले से ही बड़े बफ़र्स होते हैं - एक इंटरमीडिएट बफर पर कॉपी करने से ओएस कॉल की संख्या कम नहीं होगी, और अतिरिक्त काम का परिचय होगा।

आपके डेटा को डिस्क तक पहुंचाने के लिए अनफ़रवर्ड आउटपुट का कोई लेना- देना नहीं है; यह कार्यक्षमता द्वारा प्रदान की जाती है flush(), और बफ़र्ड और असंबद्ध दोनों धाराओं पर काम करती है। Unbuffered IO लिखता है, यह गारंटी नहीं देता कि डेटा भौतिक डिस्क तक पहुँच गया है - OS फ़ाइल सिस्टम आपके डेटा की एक प्रति को अनिश्चित काल के लिए होल्ड करने के लिए स्वतंत्र है, कभी भी इसे डिस्क पर नहीं लिखना चाहिए, अगर यह चाहता है। जब आप इनवॉइस करते हैं, तो इसे डिस्क पर प्रतिबद्ध करना आवश्यक है flush()। (ध्यान दें जो आपकी ओर से close()कॉल करेगा flush())।


क्या कॉलिंग की flush()गारंटी यह डिस्क पर लिखी गई है? मुझे लगा कि केवल डिस्क के बफर के साथ इसे पारित किया है।
जूनोको

2
आपको लिखना O_SYNCसुनिश्चित करने की आवश्यकता है।
moshbear

डिस्क पर लिखे जाने के बारे में अनभिज्ञ IO ks। इसलिए अनपेफर्ड शब्द (कोई मध्यवर्ती बफ़र नहीं, बल्कि सीधे डिस्क पर लिखा हुआ) winapi के लिए आप CreateFile को FILE_FLAG_NO_BUFFERING और FILE_FLAG_WRITE_THROUGH के साथ कॉल करते हैं ताकि यह सुनिश्चित हो सके कि प्रत्येक लिखने के बाद सीधे दृढ़ता बनी रहे। कुछ अन्य ओएस के लिए पता नहीं है।
मार्टिन कोसिके
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.