मैं एंड्रॉइड में अपने एप्लिकेशन के मेमोरी उपयोग की खोज कैसे करूं?


799

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

मुझे उम्मीद है कि ऐसा करने का एक तरीका है। साथ ही, मुझे फोन की मुफ्त मेमोरी भी कैसे मिलेगी?


2
या अगर किसी को इस सब के बारे में अधिक जानना है तो कृपया http://elinux.org/Android_Memory_Usage

1
अपने ऐप की मेमोरी डेवलपर
Shomu

जवाबों:


1007

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

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

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

सर्विस API परिवर्तन Android 2.0 से शुरू होता है

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

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

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

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

    /** 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;

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

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

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

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

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

इसके लिए SDK API बहुत अधिक है। हालाँकि, आप अपने डिवाइस के साथ एक डेवलपर के रूप में कर सकते हैं।

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

** पिड 890 में MEMINFO [प्रणाली] **
                    देशी दलविक अन्य कुल
            आकार: 10940 7047 एन / ए 17987
       आवंटित: 8943 5516 एन / ए 14459
            मुक्त: 336 1531 एन / ए 1867
           (Pss): 4585 9282 11916 25783
  (साझा गंदा): 2184 3596 916 6696
    (प्राइवेट गंदा): 4504 5956 7456 17916

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

 एसक्यूएल
            ढेर: 205 dbFiles: 0
       numPagers: 0 निष्क्रिय करेंपेजकेबी: 0
    activePageKB: 0

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

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

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

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

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

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

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

मेमोटल: 395144 kB
मेमफ्री: 184936 केबी
बफ़र: 880 kB
कैश्ड: 84104 केबी
स्वैच्च्ड: 0 केबी

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

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

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


1
Pixelbeat.org/scripts/ps_mem.py पर एक नज़र डालें, जो प्रोग्राम के लिए उपयोग की गई RAM दिखाने के लिए ऊपर वर्णित तकनीकों का उपयोग करता है
Pixelbeat

17
बहुत अच्छा लिखा है! मैंने मेमोरी प्रबंधन और विभिन्न उपकरणों के उपयोग पर एक पोस्ट लिखी है ताकि आपके ढेर के उपयोग का निरीक्षण किया जा सके। macgyverdev.blogspot.com/2011/11/… अगर किसी को यह उपयोगी लगता है।
जोहान नॉरेन

3
वास्तव में दो कॉलम "दलविक" एक "मूल" क्या हैं?
20

1
वास्तव में "देशी" "दलविक" "अन्य" क्या हैं? मेरे ऐप में, "अन्य" बहुत विशाल है? मैं इसे कैसे कम कर सकता हूं?
लैंड्री

मैं उपयोग कर सकते हैं "adb shell dumpsys meminfo", लेकिन "adb शेल procrank" मुझे बताओ।। "/ प्रणाली / bin / sh: procrank: नहीं मिला" मैं एक clue.Wish नहीं है आप मेरी मदद कर सकते
ह्यूगो

79

हाँ, आप प्रोग्रामेटिक रूप से मेमोरी जानकारी प्राप्त कर सकते हैं और यह तय कर सकते हैं कि मेमोरी इंटेंसिव कार्य करना है या नहीं।

कॉल करके VM ढेर आकार प्राप्त करें:

Runtime.getRuntime().totalMemory();

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

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

कॉल करके वीएम हीप साइज लिमिट प्राप्त करें:

Runtime.getRuntime().maxMemory()

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

Debug.getNativeHeapAllocatedSize();

मैंने OutOfMemoryError व्यवहार का पता लगाने और स्मृति उपयोग की निगरानी करने के लिए एक ऐप बनाया।

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

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


7
क्या यह रनटाइम वर्तमान प्रक्रिया या संपूर्ण सिस्टम हीप द्वारा मेमोरी उपयोग लौटाएगा?
महेंद्रन

1
टोटेमेमरी () पद्धति के जावाडॉक से @mahemadhi "मेमोरी की कुल राशि जो चल रहे कार्यक्रम के लिए उपलब्ध है" लौटाता है
एलेक्स

यह प्रश्न का सही उत्तर नहीं है। उत्तर किसी विशिष्ट एप्लिकेशन के बारे में नहीं है।
आमिर रेजाज़ादे

52

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

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");
    }
}

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


2
वे इनपुट सरणी के समान क्रम में होने की संभावना रखते हैं।
17

2
यह चीजों को करने के लिए एक बहुत ही गैर-सहज तरीका है। हाँ, यह शायद मामला है, लेकिन यह कैसे OOP किसी भी तरह से है?
रयान बेस्ले

6
एपीआई दक्षता के लिए डिज़ाइन किया गया था, उपयोग या सरलता में आसानी नहीं। यह सिर्फ कुछ ऐसा नहीं है जिसे 99% ऐप्स को कभी भी छूना चाहिए, इसलिए दक्षता सबसे महत्वपूर्ण डिज़ाइन लक्ष्य है।
हैकबॉड

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

5
यह एक मामूली समस्या है, लेकिन लॉग के लिए, यह एक लाइनफ़ीड जोड़ने के लिए आवश्यक नहीं है, जो आपके लिए संभाला जाता है।
थॉमसडब्ल्यू

24

Hackbod's, Stack Overflow पर सबसे अच्छे उत्तरों में से एक है। यह बहुत ही अस्पष्ट विषय पर प्रकाश डालता है। इसने मेरी बहुत मदद की।

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


अपडेट करें:

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


19

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

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

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

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

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

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

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


16

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

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

1
करने के लिए परिवर्तन (ActivityManager activityManager = (ActivityManager) getSystemService (ACTIVITY_SERVICE);) के बजाय (ActivityManager activityManager = = (ActivityManager) getSystemService (ACTIVITY_SERVICE);)
राजकमल

7

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

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

2

एंड्रॉइड स्टूडियो 3.0 में उन्होंने आपको यह समझने में मदद करने के लिए एंड्रॉइड-प्रोफाइलर पेश किया है कि आपका ऐप सीपीयू, मेमोरी, नेटवर्क और बैटरी संसाधनों का उपयोग कैसे करता है।

https://developer.android.com/studio/profile/android-profiler

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


1

ऊपर बहुत सारे उत्तर हैं जो निश्चित रूप से आपकी मदद करेंगे लेकिन (2 दिनों के खर्च के बाद और अदब मेमोरी टूल्स पर शोध) मुझे लगता है कि मैं अपनी राय से मदद कर सकता हूं भी ।

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

लेकिन आप किसी तर्क से इसके करीब पहुंच सकते हैं..और मैं बताऊंगा कैसे ..

कुछ API जैसे हैं android.os.Debug.MemoryInfoऔर ActivityManager.getMemoryInfo()ऊपर बताए गए हैं जिनके बारे में आप पहले से पढ़ रहे होंगे और इस्तेमाल कर रहे होंगे लेकिन मैं दूसरे तरीके के बारे में बात करूंगा

तो सबसे पहले आपको इसे काम करने के लिए एक रूट उपयोगकर्ता होने की आवश्यकता है। suप्रक्रिया में निष्पादित करके मूल विशेषाधिकार के साथ कंसोल में जाओ और प्राप्त करें output and input stream। फिर ouputstream में पास id\n (एंटर) करें और इसे आउटपुट प्रोसेस करने के लिए लिखें, अगर आपको इनपुटस्ट्रीम मिलेगा uid=0, तो आप रूट यूजर हैं।

अब यहाँ तर्क है जो आप उपरोक्त प्रक्रिया में उपयोग करेंगे

जब आप प्रक्रिया की ouputstream प्राप्त करते हैं, तो आप id के बजाय कमांड (procrank, dumpsys meminfo आदि ...) पास करते हैं\n और इसकी प्राप्तिinputstream और पढ़ते हैं, स्ट्रीम को बाइट्स में स्टोर करते हैं [], char [] आदि .. कच्चे डेटा का उपयोग करें..और कार्य पूर्ण!!!!!

अनुमति :

<uses-permission android:name="android.permission.FACTORY_TEST"/>

जांचें कि क्या आप रूट उपयोगकर्ता हैं:

// su command to get root access
Process process = Runtime.getRuntime().exec("su");         
DataOutputStream dataOutputStream = 
                           new DataOutputStream(process.getOutputStream());
DataInputStream dataInputStream = 
                           new DataInputStream(process.getInputStream());
if (dataInputStream != null && dataOutputStream != null) {
   // write id to console with enter
   dataOutputStream.writeBytes("id\n");                   
   dataOutputStream.flush();
   String Uid = dataInputStream.readLine();
   // read output and check if uid is there
   if (Uid.contains("uid=0")) {                           
      // you are root user
   } 
}

के साथ अपने आदेश निष्पादित करें su

Process process = Runtime.getRuntime().exec("su");         
DataOutputStream dataOutputStream = 
                           new DataOutputStream(process.getOutputStream());
if (dataOutputStream != null) {
 // adb command
 dataOutputStream.writeBytes("procrank\n");             
 dataOutputStream.flush();
 BufferedInputStream bufferedInputStream = 
                     new BufferedInputStream(process.getInputStream());
 // this is important as it takes times to return to next line so wait
 // else you with get empty bytes in buffered stream 
 try {
       Thread.sleep(10000);
 } catch (InterruptedException e) {                     
       e.printStackTrace();
 }
 // read buffered stream into byte,char etc.
 byte[] bff = new byte[bufferedInputStream.available()];
 bufferedInputStream.read(bff);
 bufferedInputStream.close();
 }
}

लॉगकट: परिणाम

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

यह सिर्फ एक कोशिश है, कृपया मुझे सुझाव दें अगर मैंने कुछ याद किया

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