आप एंड्रॉइड ऐप पर उपलब्ध एप्लिकेशन हीप आकार का प्रोग्राम प्रोग्राम कैसे कर सकते हैं?
मैंने सुना है कि एसडीके के बाद के संस्करणों में ऐसा कार्य होता है। किसी भी मामले में, मैं समाधान की तलाश कर रहा हूं जो 1.5 और ऊपर की ओर काम करता है।
आप एंड्रॉइड ऐप पर उपलब्ध एप्लिकेशन हीप आकार का प्रोग्राम प्रोग्राम कैसे कर सकते हैं?
मैंने सुना है कि एसडीके के बाद के संस्करणों में ऐसा कार्य होता है। किसी भी मामले में, मैं समाधान की तलाश कर रहा हूं जो 1.5 और ऊपर की ओर काम करता है।
जवाबों:
आपके वाक्यांश "एप्लिकेशन हीप आकार उपलब्ध" के बारे में सोचने के दो तरीके हैं:
एक कठिन त्रुटि शुरू होने से पहले मेरे ऐप का कितना उपयोग हो सकता है? तथा
एंड्रॉइड ओएस संस्करण की कमी और उपयोगकर्ता के डिवाइस के हार्डवेयर को देखते हुए, मेरे ऐप का कितना उपयोग करना चाहिए ?
उपरोक्त प्रत्येक को निर्धारित करने के लिए एक अलग विधि है।
आइटम 1 से ऊपर के लिए: maxMemory()
जिसे निम्न प्रकार से लागू किया जा सकता है (जैसे, आपकी मुख्य गतिविधि onCreate()
विधि में):
Runtime rt = Runtime.getRuntime();
long maxMemory = rt.maxMemory();
Log.v("onCreate", "maxMemory:" + Long.toString(maxMemory));
यह विधि आपको बताती है कि आपके ऐप को ढेर के कुल बाइट्स का उपयोग करने की अनुमति है।
आइटम 2 से ऊपर के लिए: getMemoryClass()
जिसे निम्नानुसार लागू किया जा सकता है:
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass();
Log.v("onCreate", "memoryClass:" + Integer.toString(memoryClass));
यह विधि आपको लगभग बताती है कि आपके ऐप को कितने मेगाबाइट्स का उपयोग करना चाहिए यदि वह वर्तमान डिवाइस की सीमाओं का उचित रूप से सम्मान करना चाहता है, और अन्य ऐप के अधिकारों के बिना बार-बार चलने के लिए मजबूर किया जाता है onStop()
/ onResume()
क्योंकि वे अशिष्ट हैं जब आपका हाथी ऐप एंड्रॉइड जकूज़ी में नहाता है तो मेमोरी से बाहर निकल जाता है।
यह अंतर स्पष्ट रूप से प्रलेखित नहीं है, जहां तक मुझे पता है, लेकिन मैंने पांच अलग-अलग एंड्रॉइड डिवाइसों पर इस परिकल्पना का परीक्षण किया है (नीचे देखें) और अपनी संतुष्टि की पुष्टि की है कि यह एक सही व्याख्या है।
एंड्रॉइड के स्टॉक संस्करण के लिए, maxMemory()
आमतौर पर मेगाबाइट की उसी संख्या के बारे में वापस आ जाएगा , जैसा कि getMemoryClass()
(यानी, लगभग एक मिलियन गुना बाद वाले) में इंगित किया गया है।
एकमात्र स्थिति (जिसके बारे में मुझे पता है) जिसके लिए दो विधियाँ एक रूट किए गए डिवाइस पर चल सकती हैं, जैसे कि एंड्रॉइड संस्करण जैसे कि सियानोजेनमॉड, जो उपयोगकर्ता को मैन्युअल रूप से चयन करने की अनुमति देता है कि प्रत्येक ऐप के लिए कितने बड़े आकार की अनुमति दी जानी चाहिए। उदाहरण के लिए, सीएम में, यह विकल्प "CyanogenMod सेटिंग्स" / "प्रदर्शन" / "VM ढेर आकार" के तहत दिखाई देता है।
नोट: यदि आप अपने डिवाइस के लिए सामान्य से कम मूल्य का चयन करते हैं, तो यह आपके सिस्टम को सही ढंग से उपयोग कर सकता है, तो यह निश्चित रूप से बढ़ सकता है।
यहां मेरे परीक्षण के परिणाम दिखाए गए हैं maxMemory()
और getMemoryClass()
CyanogenMod चलाने वाले चार अलग-अलग उपकरणों के लिए, प्रत्येक के लिए दो अलग-अलग (मैन्युअल रूप से-सेट) हीप मानों का उपयोग करते हुए:
उपर्युक्त के अलावा, मैंने नोवो 7 पलाडिन टैबलेट पर आइस क्रीम सैंडविच चलाने का परीक्षण किया। यह अनिवार्य रूप से आईसीएस का स्टॉक संस्करण था, सिवाय इसके कि मैंने एक सरल प्रक्रिया के माध्यम से टैबलेट को रूट किया है जो पूरे ओएस को प्रतिस्थापित नहीं करता है, और विशेष रूप से एक इंटरफ़ेस प्रदान नहीं करता है जो ढेर के आकार को मैन्युअल रूप से समायोजित करने की अनुमति देगा।
उस उपकरण के लिए, यहां परिणाम हैं:
इसके अलावा (प्रति टिप्पणी में किशोर के अनुसार):
और (प्रति अनूपकी की टिप्पणी):
Cmcromance से प्रति टिप्पणी:
और (प्रति टिप्पणी के अनुसार):
अन्य उपकरण
मैंने विशेष एंड्रॉइड का उपयोग करके इन दो तरीकों का परीक्षण नहीं किया है: हनीकॉम्ब के बाद से उपलब्ध "सच" प्रकट विकल्प, लेकिन cmcromance और तनाव के लिए धन्यवाद, हमारे पास कुछ नमूना लार्जहैप मान हैं, जैसा कि ऊपर बताया गया है।
मेरी उम्मीद (जो कि ऊपर दिए गए लार्जहैप नंबरों द्वारा समर्थित प्रतीत होती है) यह होगी कि यह विकल्प रूट ओएस के माध्यम से मैन्युअल रूप से हीप को सेट करने के समान प्रभाव होगा - अर्थात, यह अकेले maxMemory()
छोड़ते समय मूल्य बढ़ाएगा getMemoryClass()
। एक और तरीका है, getLargeMemoryClass (), जो बताता है कि लार्जहाइप सेटिंग का उपयोग करके किसी ऐप के लिए मेमोरी कितनी स्वीकार्य है। GetLargeMemoryClass () के लिए दस्तावेज़ में कहा गया है, "अधिकांश अनुप्रयोगों को स्मृति की इस राशि की आवश्यकता नहीं होनी चाहिए, और इसके बजाय getMemoryClass () सीमा के साथ रहना चाहिए।"
अगर मैंने सही तरीके से अनुमान लगाया है, तो उस विकल्प का उपयोग करने के समान लाभ (और जोखिम) होंगे जैसे कि एक उपयोगकर्ता द्वारा उपलब्ध कराए गए स्थान का उपयोग करना होगा जो एक रूट ओएस (यानी, यदि आपका ऐप अतिरिक्त मेमोरी का उपयोग करता है, तो ढेर लगा दिया है) यह शायद उतने अच्छे से नहीं खेलेगा, जितने समय में उपयोगकर्ता जितने अन्य ऐप चला रहा है)।
ध्यान दें कि मेमोरी क्लास को स्पष्ट रूप से 8MB से अधिक की आवश्यकता नहीं है।
हम ऊपर से देख सकते हैं कि getMemoryClass()
परिणाम किसी दिए गए डिवाइस / OS कॉन्फ़िगरेशन के लिए अपरिवर्तित है, जबकि अधिकतम () मान तब बदलता है जब ढेर उपयोगकर्ता द्वारा अलग तरीके से सेट किया जाता है।
मेरा अपना व्यावहारिक अनुभव यह है कि G1 पर (जिसमें 16 की मेमोरी क्लास है), अगर मैं मैन्युअल रूप से 24MB को हीप साइज़ के रूप में चुनता हूं, तो मैं बिना किसी इर्र्रेसिंग के भी चल सकता हूं, जब मेरी मेमोरी के उपयोग को 20MB की ओर बढ़ने की अनुमति है (संभवतः) के रूप में उच्च के रूप में जाना 24MB, हालांकि मैंने यह कोशिश नहीं की है)। लेकिन इसी तरह अन्य बड़े-ईश ऐप मेरे अपने ऐप के पिगमेंट के परिणामस्वरूप मेमोरी से फ्लश हो सकते हैं। और, इसके विपरीत, यदि मेरे अन्य उच्च रखरखाव वाले ऐप को उपयोगकर्ता द्वारा अग्रभूमि में लाया जाता है , तो मेरा ऐप मेमोरी से फ्लश हो सकता है।
इसलिए, आप द्वारा निर्दिष्ट मेमोरी की मात्रा से अधिक नहीं जा सकते maxMemory()
। और, आपको निर्दिष्ट सीमाओं के भीतर रहने का प्रयास करना चाहिए getMemoryClass()
। ऐसा करने का एक तरीका, यदि अन्य सभी विफल रहता है, तो ऐसे उपकरणों के लिए कार्यक्षमता को सीमित करना हो सकता है जो स्मृति को संरक्षित करते हैं।
अंत में, यदि आप निर्दिष्ट मेगाबाइट की संख्या पर जाने की योजना बनाते हैं getMemoryClass()
, तो मेरी सलाह होगी कि आप अपने ऐप की स्थिति को बचाने और बहाल करने के लिए लंबे समय तक मेहनत करें, ताकि उपयोगकर्ता का अनुभव वास्तव में निर्बाध हो onStop()
/ अगर onResume()
चक्र होता है।
मेरे मामले में, प्रदर्शन के कारणों से मैं अपने ऐप को 2.2 और उससे अधिक चलने वाले उपकरणों तक सीमित कर रहा हूं, और इसका मतलब है कि मेरे ऐप को चलाने वाले लगभग सभी डिवाइसों में 24 या उससे अधिक का मेमोरीक्लास होगा। इसलिए मैं 20MB तक के ढेर पर कब्जा करने के लिए डिज़ाइन कर सकता हूं और बहुत आश्वस्त महसूस करता हूं कि मेरा ऐप उसी समय अन्य ऐप के साथ अच्छा खेलेगा जो उपयोगकर्ता चला रहा हो।
लेकिन हमेशा कुछ जड़ वाले उपयोगकर्ता होंगे जिन्होंने एंड्रॉइड के 2.2 या इसके बाद के संस्करण को एक पुराने डिवाइस (जैसे, जी 1) पर लोड किया है। जब आप इस तरह के कॉन्फ़िगरेशन का सामना करते हैं, तो आदर्श रूप से, आपको अपने मेमोरी उपयोग को रोकना चाहिए, भले ही maxMemory()
आप यह कह रहे हों कि आप 16MB से अधिक जा सकते हैं getMemoryClass()
जो आपको बता रहा है कि आपको लक्षित होना चाहिए। और यदि आप मज़बूती से यह सुनिश्चित नहीं कर सकते हैं कि आपका ऐप उस बजट के भीतर रहेगा, तो कम से कम यह सुनिश्चित करें कि वह onStop()
/ onResume()
मूल रूप से काम करता है।
getMemoryClass()
, जैसा कि डायने हैकबॉर्न (हैकबॉड) द्वारा इंगित किया गया है, केवल एपीआई स्तर 5 (एंड्रॉइड 2.0) पर वापस उपलब्ध है, और इसलिए, जैसा कि वह सलाह देती है, आप मान सकते हैं कि ओएस के पुराने संस्करण को चलाने वाले किसी भी उपकरण का भौतिक हार्डवेयर डिज़ाइन किया गया है 16 एमबी से अधिक के ढेर स्थान पर कब्जा करने वाले ऐप्स का जानबूझकर समर्थन करने के लिए।
इसके विपरीत, maxMemory()
दस्तावेज़ीकरण के अनुसार, सभी तरह से एपीआई स्तर 1 maxMemory()
पर उपलब्ध है। प्री-2.0 संस्करण पर, संभवतः 16 एमबी मूल्य लौटाएगा, लेकिन मुझे लगता है कि मेरे (बहुत बाद में) CyanogenMod संस्करण उपयोगकर्ता 12 एमबी के रूप में कम के रूप में एक ढेर मूल्य का चयन कर सकते हैं, जो संभवतः कम हीप सीमा में परिणाम होगा, और इसलिए मैं सुझाव दूंगा कि आप maxMemory()
2.0 के पूर्व के ओएस के संस्करणों के लिए भी मूल्य का परीक्षण करना जारी रखें । आपको इस संभावना से भी इनकार करना होगा कि यह मान 16MB से कम है, यदि आपको maxMemory()
संकेत की अनुमति है तो इससे अधिक की आवश्यकता है ।
Debug.getNativeHeapSize()
चाल चलूंगा, मुझे सोचना चाहिए। यह 1.0 के बाद से वहाँ है, हालांकि।
Debug
वर्ग पर नज़र रखने के आवंटन और अन्य प्रदर्शन चिंताओं के लिए महान तरीकों की बहुत सारी है। इसके अलावा, यदि आपको कम-मेमोरी स्थिति का पता लगाने की आवश्यकता है, तो देखें Activity.onLowMemory()
।
यहाँ आप इसे कैसे करते हैं:
अधिकतम हीप आकार प्राप्त करना जो ऐप उपयोग कर सकता है:
Runtime runtime = Runtime.getRuntime();
long maxMemory=runtime.maxMemory();
वर्तमान में आपके द्वारा उपयोग किए जा रहे ऐप को कितना प्राप्त करना है:
long usedMemory=runtime.totalMemory() - runtime.freeMemory();
आपके एप्लिकेशन का अब कितना उपयोग हो सकता है (उपलब्ध मेमोरी):
long availableMemory=maxMemory-usedMemory;
और, उनमें से प्रत्येक को अच्छी तरह से प्रारूपित करने के लिए, आप उपयोग कर सकते हैं:
String formattedMemorySize=Formatter.formatShortFileSize(context,memorySize);
यह बाइट्स में अधिकतम हीप आकार देता है:
Runtime.getRuntime().maxMemory()
मैं ActivManager.getMemoryClass () का उपयोग कर रहा था, लेकिन CyanogenMod 7 पर (मैंने इसे कहीं और परीक्षण नहीं किया) यह गलत मान देता है यदि उपयोगकर्ता मैन्युअल रूप से हीप आकार सेट करता है।
getMemoryClass
लगता है कि संख्या आपके vm के लिए उपलब्ध ढेर के आकार के समान नहीं हो सकती है, और चूंकि doc के लिए getNativeHeapSize
... taciturn, मुझे वास्तव Runtime.getRuntime().maxMemory()
में सबसे अच्छा जवाब लगता है।
कुछ ऑपरेशन जावा हीप स्पेस मैनेजर से तेज हैं। कुछ समय के लिए ऑपरेशन में देरी करने से मेमोरी स्पेस खाली हो सकती है। आप इस विधि का उपयोग हीप आकार की त्रुटि से बचने के लिए कर सकते हैं:
waitForGarbageCollector(new Runnable() {
@Override
public void run() {
// Your operations.
}
});
/**
* Measure used memory and give garbage collector time to free up some
* space.
*
* @param callback Callback operations to be done when memory is free.
*/
public static void waitForGarbageCollector(final Runnable callback) {
Runtime runtime;
long maxMemory;
long usedMemory;
double availableMemoryPercentage = 1.0;
final double MIN_AVAILABLE_MEMORY_PERCENTAGE = 0.1;
final int DELAY_TIME = 5 * 1000;
runtime =
Runtime.getRuntime();
maxMemory =
runtime.maxMemory();
usedMemory =
runtime.totalMemory() -
runtime.freeMemory();
availableMemoryPercentage =
1 -
(double) usedMemory /
maxMemory;
if (availableMemoryPercentage < MIN_AVAILABLE_MEMORY_PERCENTAGE) {
try {
Thread.sleep(DELAY_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
waitForGarbageCollector(
callback);
} else {
// Memory resources are availavle, go to next operation:
callback.run();
}
}
AvailableMemoryPercentage
सूत्र के अनुसार है: वर्तमान में डिवाइस की मेमोरी कितनी मुफ्त है। MIN_AVAILABLE_MEMORY_PERCENTAGE
आपका कस्टम पैरामीटर, एक सीमा है जिस पर आप कचरा संग्रहकर्ता को अपना काम करने के लिए इंतजार करना शुरू करते हैं।
आसुस नेक्सस 7 (2013) 32Gig: getMemoryClass () = 192 मैक्सिमरी () = 201326592
मैंने नेक्सस 7 पर अपने गेम को प्रोटोटाइप करने की गलती की, और फिर यह पता चला कि यह मेरी पत्नी के सामान्य 4.04 टैबलेट (मेमोरीक्लास 48, मैक्समोरी 50331648) पर लगभग तुरंत मेमोरी से बाहर चला गया था।
जब मैं मेमोरीक्लास कम होता हूं, तो कम संसाधनों को लोड करने के लिए मुझे अपनी परियोजना का पुनर्गठन करना होगा।
क्या जावा में वर्तमान ढेर का आकार देखने का कोई तरीका है? (मैं डिबगिंग के समय इसे लॉग-इन में स्पष्ट रूप से देख सकता हूं, लेकिन मैं इसे कोड में अनुकूलित करने के लिए देखने का एक तरीका चाहूंगा, जैसे कि currentheap> (मैक्सिममोरी / 2) उच्च गुणवत्ता वाले बिटमैप लोड करने में कम गुणवत्ता
क्या आपका मतलब प्रोग्रामेटिक या सिर्फ़ डेवलप होने और डीबग करने के दौरान है? यदि बाद वाला, आप उस जानकारी को ग्रहण में DDMS के नजरिए से देख सकते हैं। जब आपका एमुलेटर (संभवतः भौतिक फोन जो प्लग इन है) चल रहा है, तो यह बाईं ओर एक विंडो में सक्रिय प्रक्रियाओं को सूचीबद्ध करेगा। आप इसे चुन सकते हैं और ढेर आवंटन को ट्रैक करने का विकल्प है।
Runtime rt = Runtime.getRuntime();
rt.maxMemory()
मान है बी
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
am.getMemoryClass()
मूल्य MB है
rt
? यह कहां घोषित किया गया है?