मेमोरी-मैप्ड फ़ाइलों के क्या फायदे हैं?


89

मैं एक परियोजना के लिए मेमोरी मैप्ड फ़ाइलों पर शोध कर रहा हूं और उन लोगों से किसी भी विचार की सराहना करूंगा, जिन्होंने या तो उन्हें पहले इस्तेमाल किया है, या उनका उपयोग करने के खिलाफ फैसला किया है, और क्यों?

विशेष रूप से, मैं महत्व के क्रम में निम्नलिखित के बारे में चिंतित हूं:

  • संगामिति
  • रैंडम एक्सेस
  • प्रदर्शन
  • उपयोग में आसानी
  • पोर्टेबिलिटी

जवाबों:


56

मुझे लगता है कि वास्तव में यह फायदा है कि आप किसी फ़ाइल को पढ़ने के पारंपरिक तरीकों पर आवश्यक डेटा कॉपी की मात्रा को कम कर देते हैं।

यदि आपका एप्लिकेशन मेमोरी-मैप की गई फ़ाइल में "जगह में" डेटा का उपयोग कर सकता है, तो यह कॉपी किए बिना आ सकता है; यदि आप एक सिस्टम कॉल का उपयोग करते हैं (उदाहरण के लिए Linux के pread ()) तो इसमें आमतौर पर कर्नेल को अपने बफ़र्स से डेटा को उपयोगकर्ता स्थान में कॉपी करना शामिल होता है। यह अतिरिक्त प्रतिलिपि न केवल समय लेती है, बल्कि डेटा की इस अतिरिक्त प्रतिलिपि तक पहुँच कर CPU के कैश की प्रभावशीलता को कम कर देती है।

यदि डेटा को वास्तव में डिस्क (भौतिक I / O के रूप में) से पढ़ा जाना है, तो OS को अभी भी उन्हें पढ़ना होगा, पृष्ठ दोष शायद सिस्टम कॉल की तुलना में बेहतर प्रदर्शन-वार नहीं है, लेकिन यदि वे (यानी ओएस कैश में पहले से ही), सिद्धांत में प्रदर्शन बहुत बेहतर होना चाहिए।

नकारात्मक पक्ष में, स्मृति-मैप की गई फ़ाइलों के लिए कोई अतुल्यकालिक इंटरफ़ेस नहीं है - यदि आप किसी ऐसे पृष्ठ पर पहुंचने का प्रयास करते हैं जिसमें मैप नहीं किया गया है, तो यह पृष्ठ दोष उत्पन्न करता है, फिर थ्रेड को I / O की प्रतीक्षा करता है।


मेमोरी मैप की गई फ़ाइलों का स्पष्ट नुकसान 32-बिट ओएस पर है - आप आसानी से पता स्थान से बाहर चला सकते हैं।


4
विंडोज पर कम से कम आप एक बड़ी mmap फ़ाइल के कई 32 बिट दृश्य देख सकते हैं - जो नियमित CRT फ़ंक्शन का उपयोग करके बहुत बड़ी फ़ाइलों से निपटने की तुलना में अधिक प्रभावशाली हो सकता है
मार्टिन बेकेट

@MarkR आपने लिखा है "उनकी अतिरिक्त कॉपी करने में न केवल समय लगता है, बल्कि डेटा की इस अतिरिक्त कॉपी तक पहुंच कर सीपीयू के कैश की प्रभावशीलता कम हो जाती है। " ( जोर मेरा)। क्या आप बता सकते हैं कि कर्नेल में अतिरिक्त बफर कॉपी सीपीयू के कैश की प्रभावशीलता में कैसे बाधा डालती है?
गीक

4
@ गीक दो बार अधिक मेमोरी तक पहुंचना = दो बार जितना कैश बर्बाद हुआ (बहुत लगभग)।
user253751

49

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

रनटाइम में फ़ाइल मेमोरी मैप की जाती है, एक C-स्टाइल structसरणी में डाली जाती है , और हम उपयोगकर्ता प्रकार के रूप में मिलान वाले भाग संख्याओं को खोजने के लिए एक द्विआधारी खोज करते हैं। फ़ाइल के केवल कुछ मेमोरी पेज वास्तव में डिस्क से पढ़े जाते हैं - जो भी पृष्ठ द्विआधारी खोज के दौरान हिट होते हैं।

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

1
क्या द्विआधारी खोज धीमी नहीं होगी क्योंकि प्रत्येक प्रयास के लिए पृष्ठों को पढ़ा जाता है? या ऑपरेटिंग सिस्टम एक कुशल तरीके से इससे निपटने के लिए पर्याप्त स्मार्ट है?
jjxtra

1
मुझे लगता है कि मैमोरी I / O का उपयोग बाइनरी सर्च के लिए बेकार है, क्योंकि सर्च केवल अपेक्षाकृत दूर की मेमोरी लोकेशन में कुछ सिंगल कीज़ को एक्सेस करेगा, लेकिन प्रत्येक ऐसे अनुरोध के लिए OS 4k पेज में लोड होगा। लेकिन तब फिर से, भागों के साथ फ़ाइल ज्यादा नहीं बदलती है, इसलिए कैश इसे कवर करने में मदद करता है। लेकिन कड़ाई से बोलते हुए, मेरा मानना ​​है कि पारंपरिक मांग / पढ़ना यहां बेहतर होगा। अंत में, इन दिनों 1 मील ज्यादा नहीं है। सिर्फ रैम में ही क्यों न रखें?
सूअर

5
@ सूअर और साइकोडैड मेरा मूल उत्तर 2008 से था और इस मेमोरी मैप्ड ऑटो-कम्प्लीट फीचर का वास्तविक कार्यान्वयन 2004-2005 के आसपास था। संपूर्ण फ़ाइल को लोड करने के लिए 800-1000MB भौतिक मेमोरी का उपभोग करना हमारे उपयोगकर्ता आधार के लिए एक अच्छा समाधान नहीं था। मेमोरी मैप्ड सॉल्यूशन बहुत तेज और कुशल था। यह लात मारी और मुझे अपने शुरुआती जूनियर-डेवलपर दिनों से यह याद है। :)
ब्रायन 17

@BrianEnsink: ठीक है, यह समझ में आता है। मुझे उम्मीद नहीं थी कि प्रत्येक प्रविष्टि 1kB जितनी होगी। तब निश्चित रूप से पृष्ठांकित दृष्टिकोण अधिक कुशल हो जाता है। अच्छा :)
सूअर

22

मेमोरी मैप की गई फ़ाइलों का उपयोग पढ़ने / लिखने की पहुंच को बदलने के लिए या समवर्ती साझाकरण का समर्थन करने के लिए किया जा सकता है। जब आप उन्हें एक तंत्र के लिए उपयोग करते हैं, तो आप दूसरे को भी प्राप्त करते हैं।

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

यह बहुत आसान हो सकता है, और वर्चुअल मेमोरी इंटरफेस के आधार पर प्रदर्शन में सुधार कर सकता है। प्रदर्शन में सुधार हो सकता है क्योंकि ऑपरेटिंग सिस्टम को अब आपके सभी अन्य प्रोग्रामेटिक मेमोरी एक्सेस के साथ इस पूर्व "फाइल I / O" को प्रबंधित करने की सुविधा मिलती है, और पेजिंग एल्गोरिदम का लाभ उठा सकते हैं और इसके आगे यह समर्थन करने के लिए उपयोग कर रहा है। अपने कार्यक्रम के बाकी हिस्सों के लिए आभासी स्मृति । हालाँकि, यह आपके अंतर्निहित वर्चुअल मेमोरी सिस्टम की गुणवत्ता पर निर्भर करता है। किस्से मैंने सुना है कि सोलारिस और * बीएसडी वर्चुअल मेमोरी सिस्टम लिनक्स के वीएम सिस्टम की तुलना में बेहतर प्रदर्शन सुधार दिखा सकते हैं - लेकिन मेरे पास इसे वापस करने के लिए कोई अनुभवजन्य डेटा नहीं है। YMMV।

जब आप मैप की गई मेमोरी के माध्यम से एक ही "फ़ाइल" का उपयोग करके कई प्रक्रियाओं की संभावना पर विचार करते हैं, तो कंसीडर तस्वीर में आता है। पढ़ने / लिखने के मॉडल में, यदि दो प्रक्रियाओं ने फ़ाइल के एक ही क्षेत्र में लिखा है, तो आप बहुत आश्वस्त हो सकते हैं कि प्रक्रिया का डेटा फ़ाइल में आ जाएगा, अन्य प्रक्रिया के डेटा को अधिलेखित कर देगा। आपको एक, या दूसरा मिलेगा - लेकिन कुछ अजीब नहीं। मुझे मानना ​​होगा कि मुझे यकीन नहीं है कि यह व्यवहार किसी भी मानक द्वारा अनिवार्य है, लेकिन यह कुछ ऐसा है जिस पर आप बहुत भरोसा कर सकते हैं। (यह वास्तव में सहमत सवाल है!)

मैप की गई दुनिया में, इसके विपरीत, "लेखन" दोनों में दो प्रक्रियाओं की कल्पना करें। वे ऐसा "मेमोरी स्टोर" करके करते हैं, जिसके परिणामस्वरूप ओ / एस डेटा को डिस्क से बाहर निकालता है - अंततः। लेकिन इस बीच, ओवरलैपिंग राइट्स होने की उम्मीद की जा सकती है।

यहाँ एक उदाहरण है। कहो कि मेरे पास दो प्रक्रियाएँ हैं, दोनों 8 बाइट्स को 1024 में लिखती हैं। प्रक्रिया 1 '11111111' लिख रही है और प्रक्रिया 2 '22222222' लिख रही है। यदि वे फ़ाइल I / O का उपयोग करते हैं, तो आप कल्पना कर सकते हैं, ओ / एस में गहरी नीचे, 1s से भरा एक बफर है, और 2s से भरा एक बफर है, दोनों डिस्क पर एक ही स्थान के लिए नेतृत्व करते हैं। उनमें से एक पहले वहाँ जा रहा है, और दूसरा एक। इस मामले में, दूसरा जीतता है। हालाँकि , अगर मैं मेमोरी-मैप्ड फ़ाइल दृष्टिकोण का उपयोग कर रहा हूं, तो प्रक्रिया 1 4 बाइट्स के मेमोरी स्टोर पर जाने वाली है, इसके बाद 4 बाइट्स के अन्य मेमोरी स्टोर (चलो मान लें कि अधिकतम मेमोरी स्टोर का आकार नहीं है)। प्रक्रिया 2 एक ही काम कर रही होगी। प्रक्रियाओं के चलने के आधार पर, आप निम्नलिखित में से कोई भी देखने की उम्मीद कर सकते हैं:

11111111
22222222
11112222
22221111

इसका समाधान स्पष्ट पारस्परिक बहिष्करण का उपयोग करना है - जो शायद किसी भी घटना में एक अच्छा विचार है। आप ओ / एस पर भरोसा करने की तरह थे, वैसे भी पढ़ने / लिखने वाली फाइल I / O केस में "सही काम" करने के लिए।

क्लासिंग आपसी बहिष्कार आदिम म्यूटेक्स है। मेमोरी मैप की गई फ़ाइलों के लिए, मेरा सुझाव है कि आप एक मेमोरी-मैप किए गए म्यूटेक्स को देखें, जो कि (उदाहरण के लिए) pthread_mutex_init () का उपयोग करके उपलब्ध है।

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


1

कंसीडर एक मुद्दा होगा। रैंडम एक्सेस आसान है परफॉर्मेंस बढ़िया से बढ़िया है। उपयोग में आसानी। के रूप में अच्छा नहीं। पोर्टेबिलिटी - इतना गर्म नहीं।

मैंने उन्हें बहुत पहले एक सन सिस्टम पर इस्तेमाल किया है, और वे मेरे विचार हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.