2010-03-13 9 views
15

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

मुझे आश्चर्य है कि फ़ाइल के बीच में डेटा डालने में कितना कुशल है। मान लीजिए कि मेरे पास 1 एमबी डेटा है और फिर मैं 512 केबी ऑफसेट पर कुछ डालता हूं। फ़ाइल के अंत में मेरे डेटा को जोड़ने के लिए इसकी तुलना कितनी कुशल होगी? उदाहरण को पूरा करने के लिए बस कहें कि मैं 16 केबी डेटा डालना चाहता हूं।

मुझे लगता है कि उत्तर फ़ाइल सिस्टम के आधार पर भिन्न होता है, हालांकि मुझे लगता है कि सामान्य फाइल सिस्टम में उपयोग की जाने वाली तकनीकें काफी समान हैं और मैं बस इसकी सही धारणा प्राप्त करना चाहता हूं।

+4

fseek() et al का उपयोग करके आप बस फ़ाइल के बीच में डेटा सम्मिलित नहीं कर सकते हैं, इसलिए आपका प्रश्न मंथन है। –

+2

आप फ़ाइल के बीच में डेटा सम्मिलित नहीं कर सकते हैं (जितना आप किसी फ़ाइल या शुरुआत के मध्य से कुछ नहीं हटा सकते हैं)। सबसे अच्छा आप फ़ाइल के बीच में डेटा ओवरराइट कर सकते हैं। – dmeister

उत्तर

5

1) fseek एक प्राथमिक सिस्टम सेवा है, लेकिन एक पुस्तकालय कार्य नहीं है: IMHO नहीं, कुछ बातों को ध्यान में रखना है (अस्वीकरण मैं सिर्फ इस दिलचस्प चर्चा करने के लिए कुछ संकेत जोड़ना चाहते हैं)। इसके प्रदर्शन का मूल्यांकन करने के लिए हमें यह समझना चाहिए कि फ़ाइल स्ट्रीम लाइब्रेरी कैसे कार्यान्वित की जाती है। आम तौर पर, फ़ाइल I/O लाइब्रेरी उपयोगकर्ता स्थान में बफरिंग की एक परत जोड़ती है, इसलिए यदि वर्तमान स्थिति वर्तमान बफर के अंदर या बाहर है तो fseek का प्रदर्शन काफी भिन्न हो सकता है। साथ ही, सिस्टम सेवाओं जो I/O libary उपयोगों में बहुत भिन्न हो सकती हैं। अर्थात। कुछ सिस्टमों पर पुस्तकालय बड़े पैमाने पर फ़ाइल मेमोरी मैपिंग का उपयोग करता है यदि संभव हो तो।

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

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

कोई टिप्पणी?

+0

बेशक, सम्मिलित करने के बजाय आम तौर पर डालने से महंगी महंगी होती है, कम से कम, किसी को पिछली सामग्री को भी स्थानांतरित करना चाहिए, यानी फ़ाइल के अंत में संलग्न होना चाहिए! लेकिन पजटन के सवाल का दिलचस्प हिस्सा झुकाव ऑपरेशन प्रदर्शनों के बारे में है। कोई टिप्पणी? –

1

आप फ़ाइल के बीच में डेटा को कुशलता से केवल तभी सम्मिलित कर सकते हैं जब डेटा आकार एफएस सेक्टर का एक बहु हो, लेकिन ओएसई ऐसे फ़ंक्शंस प्रदान नहीं करता है, इसलिए आपको एफएस ड्राइवर को निम्न-स्तरीय इंटरफ़ेस का उपयोग करना होगा।

3

आइए हम ext2 एफएस और लिनक्स ओएस को उदाहरण के रूप में मान लें। मुझे नहीं लगता कि एक डालने और संलग्न करने के बीच एक महत्वपूर्ण प्रदर्शन अंतर होगा। दोनों स्थितियों में फाइल नोड और ऑफ़सेट तालिका को पढ़ा जाना चाहिए, संबंधित डिस्क क्षेत्र मेमोरी में मैप किया गया है, डेटा अपडेट किया गया है और बाद में डिस्क पर लिखे गए डेटा को इंगित किया गया है। फ़ाइल के कुछ हिस्सों तक पहुंचने पर इस उदाहरण में एक बड़ा प्रदर्शन अंतर अच्छा अस्थायी और स्थानिक इलाका होगा क्योंकि इससे लोड/स्टोर कोम्बो की संख्या कम हो जाएगी।

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

1

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

2

fseek(...) एक लाइब्रेरी कॉल है, न कि ओएस सिस्टम कॉल। यह रन-टाइम लाइब्रेरी है जो ओएस को सिस्टम कॉल करने में शामिल वास्तविक ओवरहेड का ख्याल रखती है, तकनीकी रूप से बोलते हुए, fseek अप्रत्यक्ष रूप से सिस्टम को कॉल कर रहा है लेकिन वास्तव में यह नहीं है (यह बीच के बीच स्पष्ट अंतर लाता है लाइब्रेरी कॉल और सिस्टम कॉल के बीच अंतर)। fseek(...) अंतर्निहित प्रणाली का एक मानक इनपुट-आउटपुट समारोह परवाह किए बिना है ... लेकिन ... और यह एक बड़ा तथापि ...

ओएस की तुलना में अधिक होने की संभावना अपने कर्नेल स्मृति में फ़ाइल कैश की गई है करने के लिए नहीं है , यानी, डिस्क पर उस स्थान पर सीधा ऑफसेट जहां 1 और 0 के संग्रहित हैं, यह ओएस की कर्नेल परतों के माध्यम से, संभवतः अधिक है, कर्नेल के भीतर एक शीर्ष-सबसे परत है जिसमें स्नैपशॉट होगा फाइल से बना है, यानी डेटा इसमें अनजाने में डेटा है (यह किसी भी तरह से परवाह नहीं करता है, जब तक डिस्क पर लांचेशन के लिए उस ऑफसेट के लिए डिस्क संरचना के 'पॉइंटर्स' वैध है!) ...

जब fseek(..) होता है, तो वहां डी बहुत अधिक सिर, अप्रत्यक्ष रूप से, कर्नेल ने डिस्क से पढ़ने का कार्य सौंपा, इस पर निर्भर करता है कि फ़ाइल कितनी खंडित है, यह सैद्धांतिक रूप से, "सभी जगह" हो सकती है, जो एक महत्वपूर्ण ओवर-हेड हो सकती है उपयोगकर्ता-भूमि परिप्रेक्ष्य से, यानी सी कोड fseek(...) कर रहा है, यह डेटा को "डेटा के एक संगत दृश्य" में एकत्रित करने के लिए स्वयं को जगह पर बिखरा सकता है और अब से, इसमें डालने फ़ाइल के बीच, (इस चरण में याद रखें, कर्नेल को डेटा के लिए वास्तविक डिस्क प्लेटर में स्थान/ऑफसेट को समायोजित करना होगा) फ़ाइल के अंत में जोड़ने से धीमे समझा जाएगा।

कारण काफी सरल है, कर्नेल "जानता है" आखिरी ऑफसेट क्या था, और बस ईओएफ मार्कर को मिटा दें और दृश्यों के पीछे अधिक डेटा डालें, कर्नेल को स्मृति के दूसरे ब्लॉक को आवंटित करना है डेटा संलग्न करने के बाद, एक ईओएफ मार्कर के बाद डिस्क पर स्थान पर समायोजित ऑफ़सेट के साथ डिस्क-बफर।

+0

अच्छा संकेत, डेटा बिखरने खराब प्रदर्शन का एक महत्वपूर्ण कारण हो सकता है। धन्यवाद! –

2

एक अवलोकन मैंने सोलारिस पर fseek बनाया है, यह है कि प्रत्येक कॉल को FILE के पढ़ने वाले बफर को रीसेट करता है। अगला पठन हमेशा एक पूर्ण ब्लॉक (डिफ़ॉल्ट रूप से 8K) पढ़ेगा। इसलिए यदि आपके पास छोटे पढ़ने के साथ बहुत यादृच्छिक पहुंच है तो इसे NULL बफर के साथ) या यहां तक ​​कि सीधे सिस्कोल (lseek + read या इससे भी बेहतर pread का उपयोग करना एक अच्छा विचार है जो 2 के बजाय केवल 1 सिस्कल है)। मुझे लगता है कि यह व्यवहार अन्य ओएस पर समान होगा।

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