दिलचस्प पोस्ट
एचटीएमएल एचटीएमएल सहायक का उपयोग कर लेबल के अंदर मैंने अपने सॉफ़्टवेयर को इंटरनेट पर टूट डाउनलोड किया है, क्या करना है? पायथन / मेटप्ललिब: एक 3 डी क्यूब, एक गोलाकार और एक वेक्टर की साजिश रचने वाला? एएसपी.नेट एमवीसी रूपों में चेकबॉक्स को कैसे नियंत्रित किया जाए? पूर्ण पाठ खोज इंजन की तुलना – ल्यूसीन, स्फिंक्स, पोस्टग्रेस्क्ल, माईएसक्यूएल? मैं JSON को CSV में कैसे रूपांतरित कर सकता / सकती हूं? क्यों फ़ायरफ़ॉक्स के लिए ग़रक़ीडर की जरूरत है? WPF में मौजूदा नियंत्रणों के लिए नियंत्रण टेम्पलेट पिकासो लाइब्रेरी, एंड्रॉइड: त्रुटि सुनने वाला का उपयोग करना सी और सी ++ में डेफोग्राफ क्यों हैं? SHA-256 एन्क्रिप्टेड स्ट्रिंग को कैसे डिक्रिप्ट करें? std :: vector :: resize () बनाम std :: vector :: reserve () Reinterpret_cast का उपयोग कब करना है? Jquery इनपुट सरणी क्षेत्र प्राप्त करें "ढीली वस्तुओं" क्या हैं जो कि जीआईटी जीयूआई का उल्लेख है?

एंड्रॉइड में अपने आवेदन के मेमोरी उपयोग को कैसे प्राप्त करूं?

मैं अपने एंड्रॉइड एपलीकेशन में इस्तेमाल की जाने वाली मेमोरी को किस तरह से पा सकते हैं?

मुझे उम्मीद है कि ऐसा करने का एक तरीका है। इसके अलावा, मैं फोन की मुफ्त मेमोरी कैसे प्राप्त करूं?

Solutions Collecting From Web of "एंड्रॉइड में अपने आवेदन के मेमोरी उपयोग को कैसे प्राप्त करूं?"

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

ध्यान दें: अब हमारे पास अपनी ऐप की मेमोरीज़ के बारे में अधिक व्यापक दस्तावेज हैं, जो यहां अधिकतर सामग्री को शामिल करता है और एंड्रॉइड की स्थिति के साथ अधिक अद्यतित है।

पहली बात शायद इस लेख के अंतिम भाग को पढ़ना है जिसमें एंड्रॉइड पर मेमोरी का प्रबंधन करने की कुछ चर्चा है:

एंड्रॉइड 2.0 से शुरू होने वाले सेवा एपीआई परिवर्तन

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

निम्न-स्तर तक जा रहे हैं, आप स्मृति उपयोग के बारे में कच्चे कर्नेल-स्तर की जानकारी प्राप्त करने के लिए डीबग API का उपयोग कर सकते हैं: android.os.Debug.MemoryInfo

2.0 से शुरू होने वाला नोट एक अन्य प्रक्रिया के बारे में यह जानकारी प्राप्त करने के लिए एक API, ActivityManager.getProcessMemoryInfo भी है: ActivityManager.getProcessMemoryInfo (int [])

यह सभी डेटा के साथ एक निम्न-स्तरीय मेमोरीइन्फो संरचना देता है:

  /** The proportional set size for dalvik. */ public int dalvikPss; /** The private dirty pages used by dalvik. */ public int dalvikPrivateDirty; /** The shared dirty pages used by dalvik. */ public int dalvikSharedDirty; /** The proportional set size for the native heap. */ public int nativePss; /** The private dirty pages used by the native heap. */ public int nativePrivateDirty; /** The shared dirty pages used by the native heap. */ public int nativeSharedDirty; /** The proportional set size for everything else. */ public int otherPss; /** The private dirty pages used by everything else. */ public int otherPrivateDirty; /** The shared dirty pages used by everything else. */ public int otherSharedDirty; 

लेकिन PrivateDirty , PrivateDirty , और SharedDirty बीच अंतर क्या है … ठीक है अब मज़ा शुरू होता है।

एंड्रॉइड में बहुत सारी मेमोरी (और सामान्य रूप से लिनक्स सिस्टम) वास्तव में कई प्रक्रियाओं में साझा की जाती हैं तो प्रक्रियाओं का उपयोग कितना स्मृति वास्तव में स्पष्ट नहीं है। उस पेजिंग के शीर्ष पर डिस्क पर जोड़ें (अकेले स्वैप जिसे हम एंड्रॉइड पर उपयोग नहीं करते हैं) और यह भी कम स्पष्ट है।

इस प्रकार यदि आप सभी भौतिक RAM को वास्तव में प्रत्येक प्रक्रिया में मैप कर लेते, और सभी प्रक्रियाओं को जोड़ते, तो संभवतः आप वास्तविक कुल रैम से अधिक संख्या के साथ समाप्त हो जाएंगे।

Pss संख्या एक मैट्रिक है जो कर्नेल गणना करता है जो खाता स्मृति साझाकरण में ले जाता है – मूल रूप से किसी एक प्रक्रिया में रैम के प्रत्येक पृष्ठ को उस पृष्ठ का उपयोग करते हुए अन्य प्रक्रियाओं की संख्या के अनुपात से बढ़ाया जाता है। इस तरह से आप (सिद्धांत में) सभी प्रक्रियाओं में पीएसएस को जोड़ सकते हैं, जो कुल रैम का उपयोग कर रहे हैं, और उनके सापेक्ष वजन के किसी न किसी विचार को प्राप्त करने के लिए प्रक्रियाओं के बीच पीएसएस की तुलना करते हैं।

यहां अन्य दिलचस्प मीट्रिक है PrivateDirty , जो मूल रूप से ऐसी प्रक्रिया के अंदर रैम की मात्रा होती है जिसे डिस्क पर पेज नहीं किया जा सकता (यह डिस्क पर समान डेटा के साथ बैकअप नहीं है), और किसी भी अन्य प्रक्रियाओं के साथ साझा नहीं किया जाता है यह देखने के लिए एक और तरीका है कि जब प्रणाली समाप्त हो जाती है (और संभवत: इसे कैश और अन्य उपयोगों में जमा हो जाती है) तब सिस्टम में उपलब्ध हो जाएगा।

इसके लिए एसडीके एपीआई बहुत ज्यादा है हालांकि अधिक है आप अपने डिवाइस के साथ डेवलपर के रूप में कर सकते हैं।

adb का उपयोग करना, बहुत सी जानकारी है जो आप चल रहे सिस्टम के स्मृति उपयोग के बारे में प्राप्त कर सकते हैं। एक आम adb shell dumpsys meminfo कमांड है जो प्रत्येक जावा प्रक्रिया के स्मृति उपयोग के बारे में जानकारी का एक गुच्छा छोड़ देगा, जिसमें ऊपर की जानकारी और साथ ही अन्य चीजों की विविधता शामिल होगी। आप देख सकते हैं कि एक सिंगल प्रोसेस के नाम या adb shell dumpsys meminfo system कर सकते हैं, उदाहरण के लिए adb shell dumpsys meminfo system मुझे सिस्टम प्रोसेस प्रदान करते हैं:

 ** पिप 890 में MEMINFO [सिस्टम] **
                     देशी कुल मिलाकर कुल मिलाकर
             आकार: 10940 7047 एन / ए 17 9 87
        आवंटित: 8943 5516 एन / ए 14459
             नि: शुल्क: 336 1531 एन / ए 1867
            (पी एस): 4585 9282 11916 25783
   (साझा गंदी): 2184 35 9 6 6 6 6 6 6 6
     (निजी गंदी): 4504 5956 7456 17 9 16

  वस्तुओं
            दृश्य: 149 देखें रूट: 4
      AppContexts: 13 गतिविधियां: 0
           संपत्ति: 4 एसेट मैनेजर: 4
    स्थानीय बाइंडर्स: 141 प्रॉक्सी बाइंडर्स: 158
 मौत प्राप्तकर्ता: 49
  ओपनएसएसएल सॉकेट: 0

  एसक्यूएल
             ढेर: 205 डीबीफ़ाइलें: 0
        numpagers: 0 निष्क्रिय पृष्ठकबी: 0
     activePageKB: 0

शीर्ष खंड मुख्य एक है, जहां size एक विशेष ढेर के पते के स्थान में कुल आकार है, allocated वास्तविक आवंटन के केबी है जो ढेर के बारे में सोचता है कि यह है, free शेष केबी मुफ्त है, जो अतिरिक्त आवंटन के लिए है, और pss और priv dirty समान हैं, जैसा कि प्रत्येक ढेर के साथ जुड़े पृष्ठों के लिए विशिष्ट होने से पहले चर्चा की जाती है।

यदि आप सभी प्रक्रियाओं में मेमोरी उपयोग देखना चाहते हैं, तो आप adb shell procrank कमांड का उपयोग कर सकते हैं। उसी सिस्टम पर इसके उत्पादन का ऐसा दिखता है:

   पीआईडी ​​वीएसएस आरएसएस पीएस यूएस सीएमडीलाइन
   890 84456K 48668 के 25850 के 21284के सिस्टम_सर्वर
  1231 50748 के 39088 के 17587 के 13792के com.android.launcher2
   947 34488 के 28528 के 10834 के 9308 के कॉम। एंड्रॉइड
   987 26 9 64 के 26 9 56 क्यू 8751 के 7308 के। Com.google.process.gapps
   954 24300 के 24296 के 624 9के 4824 क। Com.android.phone
   948 23020 के 23016 के 5864 के 4748 के। Com.android.inputmethod.latin
   888 25728 के 25724 के 5774 के 3668 के युग्मज
   977 24100K 24096 के 5667 के 4340K एंड्रॉइड। प्रोसेस.कोर
 ...
    59 336 के 332 के 99 के 92 के / सिस्टम / बिन / installd
    60 396 के 392 के 93 के 84K / प्रणाली / बिन / कीस्टस्टोर
    51 280 के 276 के 74K 68 के / सिस्टम / बिन / सैनिकों
    54 256 के 252 के 69 के 64 के / सिस्टम / बिन / डीबगर

यहां Vss और Rss कॉलम मूल रूप से शोर हैं (ये सीधे-आगे वाले पते की जगह हैं और एक प्रक्रिया का उपयोग RAM, जहां आप एक हास्यास्पद बड़ी संख्या में सभी प्रक्रियाओं में रैम का इस्तेमाल करते हैं)।

Pss जैसा हम पहले देखा है, और Uss Priv Dirty

यहां दिलचस्प बात यह है कि Pss और Uss थोड़ा (या थोड़ा अधिक से अधिक) meminfo में जो हमने देखा है meminfo थोड़ा अलग है। ऐसा क्यों है? खैर procrank एक अलग कर्नेल तंत्र का उपयोग करता है meminfo करता है इसके डेटा को इकट्ठा करने के लिए, और वे थोड़ा अलग परिणाम देते हैं। ऐसा क्यों है? ईमानदारी से मैं एक सुराग नहीं है मेरा मानना ​​है कि procrank अधिक सटीक हो सकता है … लेकिन वास्तव में, यह सिर्फ इस बात को छोड़ दें: "नमक के एक अनाज के साथ मिलने वाली कोई स्मृति जानकारी ले लो, अक्सर बहुत बड़ा अनाज।"

अंत में adb shell cat /proc/meminfo कमांड है जो सिस्टम के समग्र स्मृति उपयोग का सारांश देता है। यहां बहुत सारे आंकड़े हैं, केवल चर्चा करने के पहले ही कुछ संख्याएं (और बाकी लोगों को कुछ लोगों द्वारा समझा जाता है, और उनके बारे में उन कुछ लोगों के मेरे प्रश्न अक्सर परस्पर विरोधी स्पष्टीकरण उत्पन्न करते हैं):

 MemTotal: 395144 केबी
 MemFree: 184936 केबी
 बफ़र: 880 केबी
 कैश्ड: 84104 केबी
 स्वैप कैश्ड: 0 केबी

MemTotal कर्नेल और उपयोगकर्ता स्थान के लिए उपलब्ध स्मृति की कुल राशि है (अक्सर डिवाइस की वास्तविक भौतिक RAM से कम होती है, क्योंकि रेडियो के कुछ रैम, डीएमए बफ़र्स इत्यादि के लिए आवश्यक है)।

MemFree रैम की मात्रा है जिसका उपयोग बिल्कुल भी नहीं किया जा रहा है। आप यहां देखे गए नंबर बहुत अधिक हैं; आम तौर पर एक एंड्रॉइड सिस्टम पर यह केवल कुछ एमबी होगा, क्योंकि हम प्रक्रियाओं को चलाने के लिए उपलब्ध स्मृति का उपयोग करने की कोशिश करते हैं

Cached है जो फाइल सिस्टम कैश और अन्य ऐसी चीजों के लिए इस्तेमाल किया जा रहा रैम है। खराब पेजिंग राज्यों में आने से बचने के लिए विशिष्ट सिस्टमों को इसके लिए 20 एमबी या उससे अधिक की आवश्यकता होगी; एंड्रॉइड मेमोरी किलर के बाहर एक विशिष्ट सिस्टम के लिए ट्यून किया जाता है ताकि यह सुनिश्चित किया जा सके कि पृष्ठभूमि की प्रक्रिया को मार दिया जाता है इससे पहले कि कैश रैम का उपयोग इस तरह के पेजिंग के परिणामस्वरूप ज्यादा होता है।

हां, आप मेमोरी इंफॉर्मेशन प्रोग्राम को प्राप्त कर सकते हैं और तय कर सकते हैं कि मेमोरी गहन कार्य करना है या नहीं।

कॉल करके वीएम हीप आकार प्राप्त करें:

 Runtime.getRuntime().totalMemory(); 

कॉल करके वी एम मेमोरी आवंटित करें:

 Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); 

कॉल करके वीएम हीप आकार सीमा प्राप्त करें:

 Runtime.getRuntime().maxMemory() 

कॉल करके मूल आवंटित मेमोरी प्राप्त करें:

 Debug.getNativeHeapAllocatedSize(); 

मैंने आउटऑफममेरी एरेर व्यवहार का पता लगाने और स्मृति उपयोग मॉनिटर करने के लिए एक एप बनाया है।

https://play.google.com/store/apps/details?id=net.coocood.oomresearch

आप https://github.com/coocood/oom-research पर स्रोत कोड प्राप्त कर सकते हैं

यह कार्य प्रगति पर है, लेकिन यह वही है जो मुझे समझ में नहीं आता है:

 ActivityManager activityManager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE); MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); activityManager.getMemoryInfo(memoryInfo); Log.i(TAG, " memoryInfo.availMem " + memoryInfo.availMem + "\n" ); Log.i(TAG, " memoryInfo.lowMemory " + memoryInfo.lowMemory + "\n" ); Log.i(TAG, " memoryInfo.threshold " + memoryInfo.threshold + "\n" ); List<RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses(); Map<Integer, String> pidMap = new TreeMap<Integer, String>(); for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses) { pidMap.put(runningAppProcessInfo.pid, runningAppProcessInfo.processName); } Collection<Integer> keys = pidMap.keySet(); for(int key : keys) { int pids[] = new int[1]; pids[0] = key; android.os.Debug.MemoryInfo[] memoryInfoArray = activityManager.getProcessMemoryInfo(pids); for(android.os.Debug.MemoryInfo pidMemoryInfo: memoryInfoArray) { Log.i(TAG, String.format("** MEMINFO in pid %d [%s] **\n",pids[0],pidMap.get(pids[0]))); Log.i(TAG, " pidMemoryInfo.getTotalPrivateDirty(): " + pidMemoryInfo.getTotalPrivateDirty() + "\n"); Log.i(TAG, " pidMemoryInfo.getTotalPss(): " + pidMemoryInfo.getTotalPss() + "\n"); Log.i(TAG, " pidMemoryInfo.getTotalSharedDirty(): " + pidMemoryInfo.getTotalSharedDirty() + "\n"); } } 

गतिविधि MANager.getProcessMemoryInfo () में परिणाम के लिए पीआईडी ​​मैप क्यों नहीं है? स्पष्ट रूप से आप परिणामी डेटा को सार्थक बनाना चाहते हैं, इसलिए Google ने परिणामों को सहसंबंधित करने के लिए इतना मुश्किल क्यों बनाया है? वर्तमान प्रणाली भी अच्छी तरह से काम नहीं करती है अगर मैं पूरी स्मृति उपयोग को संसाधित करना चाहता हूं क्योंकि रिटर्न परिणाम Android.os.Debug.MemoryInfo ऑब्जेक्ट्स की एक सरणी है, लेकिन उन ऑब्जेक्ट्स में से कोई भी वास्तव में आपको यह नहीं बताता कि वे किस पाइड्स से जुड़े हैं यदि आप सभी पीड्स की सरणी में बस जाते हैं, तो आपको परिणामों को समझने का कोई रास्ता नहीं होगा। जैसा कि मैंने समझ लिया है कि इसका इस्तेमाल होता है, यह एक बार में एक से अधिक पड्ड में पारित करने के लिए व्यर्थ है, और तब यदि ऐसा मामला है, तो ऐसा क्यों करें कि activityManager.getProcessMemoryInfo () केवल एक पूर्णांक सरणी लेता है?

हैकबोड स्टैक ओवरफ़्लो पर सबसे अच्छा जवाब में से एक है यह एक बहुत अस्पष्ट विषय पर प्रकाश फेंकता है इसने मेरी बहुत मदद की।

एक और बहुत ही उपयोगी संसाधन यह देखना चाहिए वीडियो: Google I / O 2011: एंड्रॉइड ऐप्स के लिए मेमोरी प्रबंधन


अद्यतन करें:

प्रोसेस स्टैट्स, यह पता लगाने के लिए एक तरीका है कि आपकी ऐप मेमोरी का प्रबंधन कैसे करती है, ब्लॉग पोस्ट पर समझाया प्रक्रिया आंकड़े: समझना कि आपका ऐप रीम का उपयोग कैसे करता है डियान हैकबॉर्न:

1) मुझे नहीं लगता, कम से कम जावा से नहीं
2)

 ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); MemoryInfo mi = new MemoryInfo(); activityManager.getMemoryInfo(mi); Log.i("memory free", "" + mi.availMem); 

एंड्रॉइड स्टूडियो 0.8.10+ ने मेमोरी मॉनिटर नामक अविश्वसनीय रूप से उपयोगी उपकरण पेश किया है।

यहां छवि विवरण दर्ज करें

इसके लिए क्या अच्छा है:

  • एक ग्राफ में उपलब्ध और उपयोग की जाने वाली स्मृति और समय के साथ कचरा संग्रह की घटनाओं को दिखा रहा है।
  • जल्दी से यह परीक्षण करें कि ऐप धीमी गति से अत्यधिक कचरा संग्रहण ईवेंट से संबंधित हो सकता है या नहीं।
  • जल्दी से परीक्षण करें कि ऐप क्रैश मेमोरी से बाहर चलने से संबंधित हो सकता है या नहीं।

यहां छवि विवरण दर्ज करें

चित्रा 1. एंड्रॉइड मेमोरी मॉनिटर पर जीसी (कूड़ा संग्रह) की घटना को मजबूर करना

आप अपने ऐप की रैम रीयल-टाइम खपत पर इसका उपयोग करके बहुत अच्छी जानकारी प्राप्त कर सकते हैं।

हमें पता चला है कि वर्तमान प्रक्रिया की कुल स्मृति प्राप्त करने के सभी मानक तरीकों में कुछ समस्याएं हैं।

  • Runtime.getRuntime().totalMemory() : केवल जेवीएम मेमोरी देता है
  • ActivityManager.getMemoryInfo() , Process.getFreeMemory() और /proc/meminfo पर आधारित कुछ भी – संयुक्त सभी प्रक्रियाओं के बारे में स्मृति जानकारी देता है (जैसे /proc/meminfo Process.getFreeMemory() )
  • Debug.getNativeHeapAllocatedSize()Debug.getNativeHeapAllocatedSize() का उपयोग करता है जो कि malloc() और संबंधित फ़ंक्शंस द्वारा mallinfo() स्मृति आवंटन के बारे में जानकारी देता है ( android_os_Debug.cpp देखें)
  • Debug.getMemoryInfo() – काम करता है लेकिन यह बहुत धीमा है। यह एक कॉल के लिए नेक्सस 6 पर लगभग 200 मीटर लेता है। प्रदर्शन ओवरहेड हमारे लिए यह फ़ंक्शन बेकार बनाता है क्योंकि हम इसे नियमित रूप से कहते हैं और प्रत्येक कॉल काफी ध्यान देने योग्य है ( android_os_Debug.cpp देखें)
  • ActivityManager.getProcessMemoryInfo(int[]) – कॉल Debug.getMemoryInfo() आंतरिक रूप से देखें ( ActivityManagerService.java देखें)

अंत में, हम निम्नलिखित कोड का उपयोग कर समाप्त हो गए:

 const long pageSize = 4 * 1024; //`sysconf(_SC_PAGESIZE)` string stats = File.ReadAllText("/proc/self/statm"); var statsArr = stats.Split(new [] {' ', '\t', '\n'}, 3); if( statsArr.Length < 2 ) throw new Exception("Parsing error of /proc/self/statm: " + stats); return long.Parse(statsArr[1]) * pageSize; 

यह VmRSS मीट्रिक देता है आप इसके बारे में यहां अधिक जानकारी पा सकते हैं: एक , दो और तीन


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

 Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memInfo); long res = memInfo.getTotalPrivateDirty(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) res += memInfo.getTotalPrivateClean(); return res * 1024L;