java - टरनल - मेमोरी कार्ड सेटिंग




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

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

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

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

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


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

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

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

कुछ एपीआई हैं जैसे android.os.Debug.MemoryInfo और ActivityManager.getMemoryInfo() ऊपर वर्णित है, जिसे आप पहले ही पढ़ सकते हैं और इस्तेमाल कर सकते हैं लेकिन मैं किसी अन्य तरीके (अप्रत्यक्ष एक) के बारे में बात करूंगा।

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

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

जब आप प्रक्रिया के ouputstream प्राप्त करते हैं तो आप आईडी के बजाय \n साथ आदेश (procrank, dumpsys meminfo आदि ...) प्राप्त करते हैं और इसके inputstream प्राप्त करते हैं और पढ़ते हैं, धारा को बाइट्स, चार आदि में स्टोर करते हैं .. कच्चे डेटा का उपयोग करें..और आप हैं किया हुआ!!!!!

अनुमति :

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

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

try {
    // 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")) {                           
             // yes sir you are root user
         } 
    }
} catch (Exception e) {
}

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

try {
      // 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();
      }
} catch (Exception e) {
}

लॉगकैट:

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

यह सिर्फ एक कोशिश है, अगर मैं गलत हूं तो कृपया मुझे सही करें


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

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

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

सेवा एपीआई एंड्रॉइड 2.0 के साथ शुरू होता है

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

निम्न स्तर पर जाकर, आप स्मृति उपयोग के बारे में कच्चे कर्नेल-स्तर की जानकारी प्राप्त करने के लिए डीबग एपीआई का उपयोग कर सकते हैं: 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;

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

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

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

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

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

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

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

** MEMINFO in pid 890 [system] **
                    native   dalvik    other    total
            size:    10940     7047      N/A    17987
       allocated:     8943     5516      N/A    14459
            free:      336     1531      N/A     1867
           (Pss):     4585     9282    11916    25783
  (shared dirty):     2184     3596      916     6696
    (priv dirty):     4504     5956     7456    17916

 Objects
           Views:      149        ViewRoots:        4
     AppContexts:       13       Activities:        0
          Assets:        4    AssetManagers:        4
   Local Binders:      141    Proxy Binders:      158
Death Recipients:       49
 OpenSSL Sockets:        0

 SQL
            heap:      205          dbFiles:        0
       numPagers:        0   inactivePageKB:        0
    activePageKB:        0

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

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

  PID      Vss      Rss      Pss      Uss  cmdline
  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  zygote
  977   24100K   24096K    5667K    4340K  android.process.acore
...
   59     336K     332K      99K      92K  /system/bin/installd
   60     396K     392K      93K      84K  /system/bin/keystore
   51     280K     276K      74K      68K  /system/bin/servicemanager
   54     256K     252K      69K      64K  /system/bin/debuggerd

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

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

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

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

MemTotal:         395144 kB
MemFree:          184936 kB
Buffers:             880 kB
Cached:            84104 kB
SwapCached:            0 kB

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

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

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


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

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 ऑब्जेक्ट्स की एक सरणी है, लेकिन उनमें से कोई भी वस्तु वास्तव में आपको बताती है कि वे किस पिड से जुड़े हुए हैं। यदि आप बस सभी बोलियों की एक सरणी में गुजरते हैं, तो आपके पास परिणामों को समझने का कोई तरीका नहीं होगा। जैसा कि मैं समझता हूं कि इसका उपयोग होता है, यह एक समय में एक से अधिक पिड में गुजरने के लिए व्यर्थ बनाता है, और फिर यदि ऐसा है, तो ऐसा क्यों करें कि गतिविधि प्रबंधक.getProcessMemoryInfo () केवल एक int सरणी लेता है?


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

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

Runtime.getRuntime().totalMemory();

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

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 पर स्रोत कोड प्राप्त कर सकते हैं


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

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

अद्यतन करें:

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







memory-management