मैं एक प्रक्रिया के लिए उपलब्ध स्मृति की मात्रा को कैसे सीमित कर सकता हूं?


11

मैं जाने में एक कार्यक्रम विकसित कर रहा हूं; यह कभी-कभी बहुत बड़ी मात्रा में मेमोरी (>> 8G भौतिक मेमोरी वाली मशीन पर) आवंटित करने पर समाप्त हो जाता है, जिससे सिस्टम अप्रतिसादी हो जाता है। मैं स्मृति की मात्रा को सीमित करना चाहता हूं जो प्रक्रिया आवंटित कर सकती है। सामान्य तरीके से मैं यह करूंगा:

ulimit -m 4000000 ; ./myprogram

... जो मेरे कार्यक्रम को मारना चाहिए अगर यह 4GB से अधिक मेमोरी का उपयोग करने की कोशिश करता है।

OS X El Capitan पर इसका कोई प्रभाव नहीं दिखता है; यहां तक ​​कि ulimit -m 1(स्मृति के सिर्फ 1kB के लिए सभी कार्यक्रमों को सीमित!) अप्रभावी है।

मैं किसी विशेष प्रक्रिया के लिए उपलब्ध मेमोरी पर ऊपरी बाउंड कैसे सेट कर सकता हूं?


जब आप कहते हैं कि सामान्य तरीके से मैं ऐसा करता हूं , तो आपका क्या मतलब है? विशेष रूप से, आप आमतौर पर ऐसा कब करते हैं? और जब आप इसे करते हैं, तो क्या आपका मतलब मैक ओएस एक्स एल कैपिटन या किसी अन्य वातावरण में है? क्या आप इसका उदाहरण दे सकते हैं कि आपने इसका सफलतापूर्वक उपयोग कब किया है? असल में, मैं यह स्पष्ट करने की कोशिश कर रहा हूं कि क्या यह प्रक्रिया आपके लिए सामान्य रूप से काम करती है, लेकिन सिर्फ इस विशेष कार्यक्रम के लिए काम नहीं कर रही है? या यह आपके लिए बिल्कुल भी काम नहीं कर रहा है लेकिन आपको लगता है कि यह करना चाहिए?
Monomeeth

1
"सामान्य तरीके से मैं ऐसा करूंगा", मेरा मतलब है कि मैं यूनिक्स के अन्य स्वादों पर ऐसा करूंगा। मैं ध्यान देता हूं कि मैंने अभी पता लगाया है कि ulimit -mअब लिनक्स (> २.४.३०) पर ulimit -vकाम नहीं किया जाता है , हालांकि यह अभी भी उम्मीद के मुताबिक काम करता है। (जैसे ulimit -m, ulimit -vOS X पर भी कोई प्रभाव नहीं दिखता है)
cpcallen

ऐसा लगता है कि आपने जो प्रोग्राम लिखा है उसमें मेमोरी लीक हो गई है और आपको बेहतर कचरा संग्रह करने की आवश्यकता है। क्या आपने स्मृति प्रबंधन को जाना है?
टोड दाबनी

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

जवाबों:


1

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

यदि आप पूर्व पोस्ट वास्तविक दृष्टिकोण पर जोर देते हैं, तो आप निम्नलिखित बैश स्क्रिप्ट का उपयोग कर सकते हैं। यह स्क्रिप्ट पहले मेमोरी की मात्रा ("रेजिडेंट सेट साइज" के रूप में परिभाषित करती है) प्रोसीड पीआईडी ​​के साथ प्रक्रिया का उपयोग करती है, सभी गैर संख्यात्मक डेटा को grep का उपयोग करके फ़िल्टर करती है, और इस राशि को वेरिएबल n के रूप में सहेजती है। स्क्रिप्ट तब जांचती है कि क्या n आपके निर्दिष्ट x से अधिक है। यदि यह है, तो प्रोसेसिड पिड के साथ प्रक्रिया को मार दिया जाता है।

कृपया ध्यान दें:

  1. आपको <pid>अपने प्रोग्राम के प्रोसेस आईडी से बदलना होगा ।
  2. आपको <x>rss = "निवासी सेट आकार" (यानी वास्तविक मेमोरी आकार) से बदलना होगा जो आप प्रोग्राम को पार नहीं करना चाहते हैं।

n=$(ps -<pid> -o rss | grep '[0-9]') if [ $n -gt <x> ]; then kill -9 <pid>; fi

यदि आप चाहते हैं कि यह प्रत्येक y सेकंड को चलाने के लिए है, तो इसे लूप में सम्मिलित करें, और इसे प्रत्येक पुनरावृत्ति के बाद y सेकंड के लिए प्रतीक्षा करने के लिए कहें। आप एक समान कमांड का उपयोग करके भी लिख सकते हैं top। आपका शुरुआती बिंदु होगा top -l 1|grep "<pid>"|awk '{print $10}'

@ kenorb के जवाब से मुझे अपनी स्क्रिप्ट में मदद मिली


जबकि मेरा मानना ​​है कि प्रश्न का उत्तर देता है, लंबे समय में मेरा मानना ​​है कि मैन्युअल मेमोरी आवंटन का उपयोग करते हुए प्रीमेप्टिव दृष्टिकोण लेना बेहतर प्रोग्रामिंग डिज़ाइन है।

सबसे पहले, क्या आप सुनिश्चित हैं कि मेमोरी का उपयोग वास्तव में एक समस्या है? गो प्रलेखन में कहा गया है:

गो मेमोरी एलोकेटर आवंटन के लिए एक क्षेत्र के रूप में वर्चुअल मेमोरी के एक बड़े क्षेत्र को आरक्षित करता है। यह वर्चुअल मेमोरी विशिष्ट गो प्रक्रिया के लिए स्थानीय है; आरक्षण स्मृति की अन्य प्रक्रियाओं से वंचित नहीं करता है।

यदि आपको अभी भी लगता है कि आपको कोई समस्या है, तो मैं आपको अपनी मेमोरी को मैन्युअल रूप से प्रबंधित करने के लिए प्रोत्साहित करता हूं जैसा कि सी प्रोग्रामिंग भाषा में किया गया है। चूंकि गो सी में लिखा है, मुझे संदेह है कि सी मेमोरी प्रबंधन / आवंटन में आने के तरीके होंगे, और वास्तव में वहाँ हैं। इस जीथूब भंडार को देखें ,

आपको अपने सिस्टम के लिए मानक सी एलोकेटर के माध्यम से मैनुअल मेमोरी प्रबंधन करने की अनुमति देता है। यह मॉलॉक, कॉलोक और शीर्ष पर एक पतली आवरण है। अपने सिस्टम के लिए इन कार्यों के विवरण के लिए मैन मालॉक देखें। यह पुस्तकालय cgo का उपयोग करता है।

उपयोग का मामला इस प्रकार है:

आप ऐसा क्यों चाहेंगे?

जब कोई प्रोग्राम मेमोरी प्रेशर पैदा कर रहा होता है या सिस्टम मेमोरी से बाहर चल रहा होता है तो यह मेमोरी एलोकेशन और डीलक्लोशन्स को मैन्युअल रूप से कंट्रोल करने में मददगार हो सकता है। गो आपको आवंटन को नियंत्रित करने में मदद कर सकते हैं लेकिन अनावश्यक डेटा को स्पष्ट रूप से डील करना संभव नहीं है।

यह एक बेहतर दीर्घकालिक समाधान की तरह लगता है।

यदि आप C (स्मृति प्रबंधन सहित) के बारे में अधिक जानना चाहते हैं, तो C प्रोग्रामिंग भाषा मानक संदर्भ है।


मुझे यकीन है कि स्मृति उपयोग वास्तव में एक समस्या है। जब प्रोग्राम अप्रत्याशित रूप से बढ़ गया> 2x भौतिक स्मृति आकार पेज थ्रैशिंग के कारण मशीन लगभग पूरी तरह से गैर-उत्तरदायी हो गई। जब मैंने ^ C मारा और जब macOS ने माउस क्लिक का जवाब देना शुरू किया, तो उसे लगभग एक घंटा लग गया; इस बीच में केवल सबूत है कि यह जमे हुए नहीं था हार्ड ड्राइव के शांत शोर के बारे में तेजी से टिक गया था।
cpcallen

यह शायद व्यवहार में एक उचित समाधान है, लेकिन (गैर-डार्विन) UNIX OS पर ulimit के विपरीत, यह समय पर फैशन में पर्याप्त स्मृति आवंटित करने में सक्षम है, ताकि वह सफलतापूर्वक कमांड को मार सके। मैं वास्तव में बल्कि कर्नेल द्वारा लागू की गई प्रक्रिया आकार सीमाएँ हूँ।
cpcallen

@cpcallen कुछ खोज कर रहा है ऐसा लगता है "ulmit के लिए -m पैरामीटर लिनक्स सिस्टम पर कोई प्रभाव नहीं है। कर्नेल संस्करण 2.4.30 से अधिक हाल के हैं।" ऐसा लगता है कि OSX ने भी इस बदलाव को उठाया है। पते की जगह को सीमित करने के लिए -v विकल्प आज़माएं
Evan Rosica

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