মেমরি লিমিটার

Android 17 ও তার পরবর্তী ভার্সনে মেমরি লিমিটার অন্তর্ভুক্ত থাকে, এটি একটি সিস্টেম সার্ভিস যা Linux cgroup v2 ব্যবহার করে অ্যাপ্লিকেশন প্রসেসের মেমরির ব্যবহার মনিটর ও সীমিত করে। মেমরি লিমিটার, স্বতন্ত্র অ্যাপকে সিস্টেম মেমরির অনুপযুক্ত ব্যবহার থেকে আটকায়, যা সামগ্রিক মেমরির চাপ কমায় এবং গুরুত্বপূর্ণ ফোরগ্রাউন্ড ও ক্যাশে করা প্রসেসের আগ্রাসী লো-মেমরি কিল আটকায়।

পদ্ধতি

প্রসেস লাইফসাইকেল ইভেন্ট এবং স্ট্যাটাস পরিবর্তন ট্র্যাক করতে, মেমরি লিমিটার অ্যাক্টিভিটি ম্যানেজার সার্ভিসের (AMS) সাথে ইন্টিগ্রেট করে। মেমরি লিমিটার Linux কার্নেল cgroup v2 হায়ারার্কি ব্যবহার করে মেমরি সীমা এনফোর্স করে।

মেমরি লিমিটারকে সাপোর্ট করতে, ডিভাইস কার্নেলে অবশ্যই cgroup v2 এবং memory কন্ট্রোলার চালু থাকতে হবে। পরিষেবাটি বিশেষভাবে নিম্নলিখিত অ্যাট্রিবিউটের উপর নির্ভর করে:

memory.high
একটি সফ্ট লিমিট। সীমা পেরিয়ে গেলে, প্রসেস থ্রটল করা হয় এবং কার্নেল সেই প্রসেস থেকে প্রোঅ্যাক্টিভ পৃষ্ঠা রিক্লেম করার চেষ্টা করে।
memory.swap.max
প্রসেসটি ব্যবহার করতে পারে এমন সোয়াপ স্পেসের (যেমন ZRAM) সর্বাধিক পরিমাণ সীমিত করে।

অ্যাপের উপর প্রভাব

যেসব অ্যাপ মেমরি সীমার মধ্যে কাজ করে, সেগুলির উপর মেমরি লিমিটারের কোনও প্রভাব পড়ে না।

কোনও অ্যাপ তার memory.high সীমা অতিক্রম করলে, কার্নেল অ্যাপের ক্লিন ফাইল-ব্যাকড মেমরি খালি করে দেয় এবং অ্যাপটিকে সীমার মধ্যে রাখতে এর ইনঅ্যাক্টিভ অ্যানোনিমাস মেমরি সোয়্যাপ করে। এই পৃষ্ঠাটি সরিয়ে দেওয়া এবং সোয়্যাপ অ্যাক্টিভিটির ফলে, অ্যাপটি সাময়িকভাবে এক্সিকিউশন থ্রটলিংয়ের অভিজ্ঞতা পেতে পারে, তবে এটি চলতে থাকে।

চরম পরিস্থিতিতে—যেমন, অনিয়ন্ত্রিত মেমরি লিক যেখানে অ্যাপ সয়াপ স্পেস শেষ হয়ে যাওয়ার পরেও বেনামী মেমরি বরাদ্দ করা চালিয়ে যায়—অ্যাপ মেমরি বরাদ্দ করতে ব্যর্থ হয় এবং বন্ধ হয়ে যায়।

প্রসেস মনিটরিং

মেমরি লিমিটার ডিফল্ট হিসেবে অ্যাপ প্রসেস (UID >= ১০০০০) মনিটর করে। সিস্টেমের প্রয়োজনীয় স্টেবিলিটি বজায় রাখতে সিস্টেমের মূল প্রসেসকে ছাড় দেওয়া হয়।

মেমরি লিমিটার, প্রসেসের দৃশ্যমানতার উপর ভিত্তি করে মেমরির সীমা নির্ধারণ করে:

  • দৃশ্যমান প্রসেস: ব্যবহারকারীর কাছে দৃশ্যমান UI হোস্ট করা প্রসেস (যেমন, বর্তমানে ফোকাস করা অ্যাক্টিভিটি বা অ্যাক্টিভ ইন্টার‍্যাকশন)। কারণ, UI দেখানোর জন্য রেন্ডারিং ও গ্রাফিক্স পাইপলাইনের জন্য আরও বড় ওয়ার্কিং সেট প্রয়োজন হয়, তাই দৃশ্যমান প্রসেস আরও বেশি মেমরি সীমা পায়।

  • অদৃশ্য প্রসেস: UI না দেখিয়ে ব্যাকগ্রাউন্ডে কাজ করে এমন প্রসেস (যেমন ব্যাকগ্রাউন্ড পরিষেবা বা সম্প্রচার রিসিভার)। যেহেতু এগুলি UI কম্পোনেন্ট রেন্ডার করে না, তাই এগুলি আরও বেশি বিধিনিষেধযুক্ত সীমার মধ্যে কাজ করে।

নিম্নলিখিত সারণী নির্দিষ্ট প্রসেস স্টেটকে মেমরি লিমিট শ্রেণিবিভাগে ম্যাপ করে:

প্রসেসের স্ট্যাটাসমেমরির সীমা
PERSISTENTঅবাধ
PERSISTENT_UIঅবাধ
TOPদৃশ্যমান
BOUND_TOPদৃশ্যমান
FOREGROUND_SERVICEদেখা যাবে না
BOUND_FOREGROUND_SERVICEদেখা যাবে না
IMPORTANT_FOREGROUNDদৃশ্যমান
IMPORTANT_BACKGROUNDদেখা যাবে না
TRANSIENT_BACKGROUNDদেখা যাবে না
BACKUPদেখা যাবে না
SERVICEদেখা যাবে না
RECEIVERদেখা যাবে না
TOP_SLEEPINGদৃশ্যমান
HEAVY_WEIGHTদেখা যাবে না
HOMEদেখা যাবে না
LAST_ACTIVITYদেখা যাবে না
CACHED_ACTIVITYক্যাশেড
CACHED_ACTIVITY_CLIENTক্যাশেড
CACHED_RECENTক্যাশেড
CACHED_EMPTYক্যাশেড

ক্যাশে করা অবস্থায়, প্রসেস ফ্রিজ করা হয় এবং তারপর সর্বাধিক রিক্লেম করা হয়।

কোনও প্রসেস তার জন্য বরাদ্দ memory.high সীমা অতিক্রম করলে, Memory Limiter ইভেন্টটি শনাক্ত করে এবং ডায়াগনস্টিক অ্যাকশন ট্রিগার করতে পারে, যেমন মেমরি প্রোফাইল ক্যাপচার করা বা statsd-এ কোনও অসঙ্গতি লগ করা।

কনফিগারেশন

Android 17 ও তার পরবর্তী ভার্সনে, মেমরি লিমিটার কনফিগার করা হয় /system/etc/memory-limiter-config.xml-এ সিস্টেম পার্টিশনে স্ট্যান্ডার্ড প্ল্যাটফর্ম কনফিগারেশন ফাইল ব্যবহার করে।

XML ফর্ম্যাট

কনফিগারেশন ফাইলটি memory-limiter-config.xsd-এ সংজ্ঞায়িত স্কিমা অনুসরণ করে। ফাইলটি উপলভ্য মেমরি দ্বারা অর্ডার করা একাধিক সীমা সেটকে সংজ্ঞায়িত করে; পরিষেবাটি ডিভাইসের উপলভ্য RAM-এর উপর ভিত্তি করে সর্বোচ্চ ম্যাচিং সীমা সেট বেছে নেয়। মেমোরির সব মান মেবিবাইটে (MiB) উল্লেখ করা হয়েছে।

<MemoryLimiterConfig>
  <version>1</version>
  <configList>
    <!-- RAM boundaries account for MemTotal excluding carve-outs. -->
    <limitSet>
      <!-- Limits for 16GB RAM device [14336, 18432): 10G/5G/5G/5G -->
      <minimumRequiredMemTotal>14336</minimumRequiredMemTotal>
      <maximumAllowedMemTotal>18432</maximumAllowedMemTotal>
      <memVisible>10240</memVisible>
      <memNotVisible>5120</memNotVisible>
      <swapVisible>5120</swapVisible>
      <swapNotVisible>5120</swapNotVisible>
    </limitSet>
    <limitSet>
      <!-- Limits for 12GB RAM device [9216, 14336): 8G/4G/4G/4G -->
      <minimumRequiredMemTotal>9216</minimumRequiredMemTotal>
      <maximumAllowedMemTotal>14336</maximumAllowedMemTotal>
      <memVisible>8192</memVisible>
      <memNotVisible>4096</memNotVisible>
      <swapVisible>4096</swapVisible>
      <swapNotVisible>4096</swapNotVisible>
    </limitSet>
    <limitSet>
      <!-- Limits for 8GB RAM device [6800, 9216): 5G/3G/3G/3G -->
      <minimumRequiredMemTotal>6800</minimumRequiredMemTotal>
      <maximumAllowedMemTotal>9216</maximumAllowedMemTotal>
      <memVisible>5120</memVisible>
      <memNotVisible>3072</memNotVisible>
      <swapVisible>3072</swapVisible>
      <swapNotVisible>3072</swapNotVisible>
    </limitSet>
    <limitSet>
      <!-- Limits for 6GB RAM device [4800, 6800): 4G/2G/2G/2G -->
      <minimumRequiredMemTotal>4800</minimumRequiredMemTotal>
      <maximumAllowedMemTotal>6800</maximumAllowedMemTotal>
      <memVisible>4096</memVisible>
      <memNotVisible>2048</memNotVisible>
      <swapVisible>2048</swapVisible>
      <swapNotVisible>2048</swapNotVisible>
    </limitSet>
    <limitSet>
      <!-- Limits for 4GB RAM device [3200, 4800): 2G/1G/1G/1G -->
      <minimumRequiredMemTotal>3200</minimumRequiredMemTotal>
      <maximumAllowedMemTotal>4800</maximumAllowedMemTotal>
      <memVisible>2048</memVisible>
      <memNotVisible>1024</memNotVisible>
      <swapVisible>1024</swapVisible>
      <swapNotVisible>1024</swapNotVisible>
    </limitSet>
  </configList>
</MemoryLimiterConfig>
version
কনফিগারেশন ভার্সন শনাক্তকারী একটি ধনাত্মক পূর্ণসংখ্যা। এটি অবশ্যই 1 হতে হবে।
minimumRequiredMemTotal

এই সীমা সেট করার জন্য ন্যূনতম সিস্টেম MemTotal (MiB-তে, ইনক্লুসিভ ফ্লোর) প্রয়োজন। পরিষেবাটি /proc/meminfo-এ কার্নেল দ্বারা রিপোর্ট করা মোট উপলভ্য মেমরির বিপরীতে এটি মূল্যায়ন করে।

মেমরি কার্ভ-আউট ও বাউন্ডারি বোঝা: কার্নেল MemTotal ভ্যালু থেকে হার্ডওয়্যার ও ফার্মওয়্যার মেমরি কার্ভ-আউট বাদ দেওয়ার পরে অপারেটিং সিস্টেমের অ্যাক্সেস করা ফিজিক্যাল DRAM-এর পরিমাণ বোঝা যায়। কার্ভ-আউট, GPU, বেসব্যান্ড মডেম, ক্যামেরা ISP, নিরাপদ এক্সিকিউশন এনভায়রনমেন্ট ও হাইপারভাইজারের মতো বিশেষ হার্ডওয়্যার কম্পোনেন্টের জন্য RAM রিজার্ভ করে রাখে, যা সাধারণত ৫০০ MiB থেকে ২ GiB-এর বেশি ফিজিক্যাল মেমরি ব্যবহার করে।

যেহেতু MemTotal ডিভাইসের বিজ্ঞাপিত ফিজিক্যাল DRAM-এর থেকে কম, minimumRequiredMemTotal থ্রেশহোল্ডে এই কার্ভ-আউটের জন্য একটি মার্জিন অন্তর্ভুক্ত থাকে। যেমন, ১৬ জিবি ডিভাইসকে টার্গেট করা কনফিগারেশন 16384 (১৬ জিবি)-এর পরিবর্তে 14336 (১৪ জিবি)-এর ফ্লোর নির্দিষ্ট করে এবং ১২ জিবি ডিভাইসের জন্য একটি টিয়ার 9216 (৯ জিবি)-এর ফ্লোর নির্দিষ্ট করে। এটি নিশ্চিত করে যে প্রতিটি ডিভাইস বোর্ড-লেভেল কার্ভ-আউট ভেরিয়েশন নির্বিশেষে তার উদ্দিষ্ট স্তরের সাথে মেলে।

maximumAllowedMemTotal

এই সীমা সেট করার জন্য সর্বাধিক সিস্টেম MemTotal (MiB-তে, এক্সক্লুসিভ সিলিং) প্রয়োগ করতে হবে। MemTotal এই সর্বোচ্চ সীমার থেকে বেশি বা সমান হলে, সেট করা সীমা প্রযোজ্য হয় না। ১৮,৪৩২ MiB বা তার বেশি মেমরি আছে এমন ডিভাইসের জন্য অথবা ৩,২০০ MiB-এর কম মেমরি আছে এমন ডিভাইসের জন্য, মেমরি লিমিটার কোনও সীমা প্রয়োগ করে না, প্রসেসগুলি অবাধে চলতে দেয়।

memVisible

দৃশ্যমান প্রসেসে MiB-তে সফট মেমরি সীমা (memory.high) প্রয়োগ করা হয়েছে।

memNotVisible

MiB-তে সফট মেমরি সীমা (memory.high) দেখা যায় না এমন প্রসেসে প্রয়োগ করা হয়েছে।

swapVisible

MiB-তে সয়াপ স্পেসের সীমা (memory.swap.max) দৃশ্যমান প্রসেসে প্রয়োগ করা হয়েছে।

swapNotVisible

MiB-তে সয়াপ স্পেসের সীমা (memory.swap.max) দেখা যায় না এমন প্রসেসে প্রয়োগ করা হয়েছে।

স্ট্যান্ডার্ড প্ল্যাটফর্মের সীমা

Android 17 ও তার পরবর্তী ভার্সনে, প্ল্যাটফর্মটি [floor, ceiling) রেঞ্জ ইন্টারভাল ব্যবহার করে সাধারণ ফিজিক্যাল RAM টিয়ার জুড়ে /system/etc/memory-limiter-config.xml-এ স্ট্যান্ডার্ড মেমরি এবং সোয়াপের সীমা নির্দিষ্ট করে:

টার্গেট ফিজিক্যাল RAM MemTotal রেঞ্জ [floor, ceiling)
(minimumRequiredMemTotal,
maximumAllowedMemTotal)
দৃশ্যমান মেমরির সীমা
(memVisible)
মেমরির সীমা দেখা যাচ্ছে না
(memNotVisible)
দৃশ্যমান সোয়াপ সীমা
(swapVisible)
দেখা যাচ্ছে না এমন সোয়াপের সীমা
(swapNotVisible)
১৬ জিবি [14336, 18432) মেবিবাইট ১০,২৪০ MiB (১০ GiB) ৫,১২০ মেবিবাইট (৫ গিবিবাইট) ৫,১২০ মেবিবাইট (৫ গিবিবাইট) ৫,১২০ মেবিবাইট (৫ গিবিবাইট)
১২ জিবি [9216, 14336) মেবিবাইট ৮,১৯২ MiB (৮ GiB) ৪,০৯৬ MiB (৪ GiB) ৪,০৯৬ MiB (৪ GiB) ৪,০৯৬ MiB (৪ GiB)
৮ জিবি [6800, 9216) মেবিবাইট ৫,১২০ মেবিবাইট (৫ গিবিবাইট) ৩,০৭২ মেবিবাইট (৩ গিবিবাইট) ৩,০৭২ মেবিবাইট (৩ গিবিবাইট) ৩,০৭২ মেবিবাইট (৩ গিবিবাইট)
৬ জিবি [4800, 6800) মেবিবাইট ৪,০৯৬ MiB (৪ GiB) ২,০৪৮ MiB (২ GiB) ২,০৪৮ MiB (২ GiB) ২,০৪৮ MiB (২ GiB)
৪ জিবি [3200, 4800) মেবিবাইট ২,০৪৮ MiB (২ GiB) ১,০২৪ MiB (১ GiB) ১,০২৪ MiB (১ GiB) ১,০২৪ MiB (১ GiB)

মেমরির সীমা সংক্রান্ত নীতি

মেমরি লিমিটার কনফিগারেশন নিম্নলিখিত প্ল্যাটফর্ম নীতির উপর ভিত্তি করে ডিজাইন করা হয়েছে:

  • ইকোসিস্টেমের ধারাবাহিকতা ও অ্যাপের মানানসই হওয়া: ডিভাইস জুড়ে মেমরির ধারাবাহিক সীমা Android ইকোসিস্টেম জুড়ে অ্যাপের পারফর্ম্যান্স সম্পর্কে অনুমান করতে সাহায্য করে। অ্যাপগুলি স্ট্যান্ডার্ড মেমরি প্রত্যাশার বিপরীতে তৈরি এবং পরীক্ষা করা হয়; অভিন্ন প্ল্যাটফর্ম সীমা বজায় রাখলে অপ্রত্যাশিত থ্রটলিং বা অকাল সমাপ্তি এড়ানো যায়।

  • আনুপাতিক রিসোর্স বরাদ্দকরণ: প্ল্যাটফর্মের সীমা ফিজিক্যাল RAM-এর ক্ষমতা অনুযায়ী ক্যালিব্রেট করা হয়:

    • দৃশ্যমান প্রসেস: অ্যাক্টিভ UI, কম্পোজিশন ও রেন্ডারিং ওয়ার্কলোডকে সাপোর্ট করার জন্য মোট ফিজিক্যাল RAM-এর প্রায় ১/২ থেকে ২/৩ অংশ বরাদ্দ করা হয়।
    • যেসব প্রসেস দেখা যায় না: ব্যাকগ্রাউন্ড টাস্কের জন্য মোট ফিজিক্যাল RAM-এর প্রায় ১/৪ থেকে ১/৩ অংশ বরাদ্দ করা হয়।
  • সর্বজনীনভাবে প্রযোজ্য: ডিভাইসে (UID >= 10000) আগে থেকে ইনস্টল করা সিস্টেম ও OEM অ্যাপ সহ সব অ্যাপ্লিকেশন প্রসেসের ক্ষেত্রে সীমা সমানভাবে প্রযোজ্য। মেমরি লিমিটার নির্দিষ্ট অ্যাপকে ছাড় দেওয়ার জন্য অনুমোদিত তালিকার সুবিধা দেয় না, যার ফলে সব অ্যাপ জুড়ে মেমরির সঠিক ব্যবহার নিশ্চিত করা যায়। গুরুত্বপূর্ণ ইন্টার‍্যাক্টিভ ডেমন-এ সেল্ফ-টিউনিং memory.min প্রোটেকশন ফ্লোর এবং স্বতন্ত্র সিস্টেম অ্যাপ ও পরিষেবায় আরও কঠোর, ওয়ার্কলোড-ক্যালিব্রেট করা memory.high সিলিং কনফিগার করতে, সিস্টেম মেমরি বাজেট দেখুন।

  • রানটাইম কোয়েরি API-এর অনুপস্থিতি: Android 17 এবং তার পরবর্তী ভার্সনে, অ্যাপ রান টাইমে প্রোগ্রাম্যাটিক্যালি তার অ্যাসাইন করা মেমরি সীমা কোয়েরি করতে পারে না। স্ট্যান্ডার্ড প্ল্যাটফর্মের সীমাগুলি উদার মার্জিনের সাথে সংজ্ঞায়িত করা হয় যাতে ভাল আচরণ করা অ্যাপগুলি স্বাভাবিক ব্যবহারের সময় সীমাবদ্ধতা ছাড়াই কাজ করে।

  • কার্নেল রিক্লেম ও সোয়াপ ডায়নামিক্স: কোনও অ্যাপ প্রসেস তার memory.high সীমার কাছাকাছি পৌঁছালে, Linux কার্নেল নির্দিষ্টভাবে সেই প্রসেস cgroup-এ মেমরি রিক্লেম করার নির্দেশ দেয়। এর মধ্যে ইনঅ্যাক্টিভ ফাইল-ব্যাক করা পৃষ্ঠা বাদ দেওয়া এবং ZRAM-এ কোল্ড অ্যানোনিমাস পৃষ্ঠা সোয়্যাপ করা অন্তর্ভুক্ত, যা গ্লোবাল মেমরি প্রেসার আরোপ না করেই সিস্টেম ফ্লুইডিটি বজায় রাখে।

শেল কমান্ড

am memory-limiter কমান্ড ডেভেলপার ও সিস্টেম ইন্টিগ্রেটরদের ডেভেলপমেন্ট, টেস্টিং ও ডিবাগিংয়ের জন্য রান টাইমে পরিষেবার সাথে ইন্টার‍্যাক্ট করতে দেয়:

am memory-limiter <SUB-COMMAND>

স্ট্যাটাস

status সাব-কমান্ড মেমরি লিমিটারের অপারেশনাল স্ট্যাটাস এবং অ্যাক্টিভ মেট্রিক রিপোর্ট করে:

adb shell am memory-limiter status

নিচে আউটপুটের উদাহরণ দেওয়া হল:

Memory limiter
  enabled                  monitoring=true          ignored=none
  visibleMem=1948MB        visibleSwap=974MB
  notVisibleMem=974MB      notVisibleSwap=487MB
  started=36               watched=36               watch-failed=0
  events=0                 processes=36             process-hwm=36

আউটপুটের মূল ফিল্ডের মধ্যে এগুলি অন্তর্ভুক্ত:

monitoring
মেমরি লিমিটার প্রসেসগুলি সক্রিয়ভাবে দেখছে কিনা তা নির্দেশ করে।
visibleMem ও notVisibleMem
প্রতিটি দৃশ্যমানতা অবস্থার জন্য বর্তমানে প্রয়োগ করা গণনা করা পরম মেমরি সীমা (memory.high)।
visibleSwap ও notVisibleSwap
প্রতিটি দৃশ্যমানতা অবস্থার জন্য বর্তমানে এনফোর্স করা হিসাব করা অ্যাবসোলিউট সোয়াপ সীমা (memory.swap.max)।
events
কোনও প্রসেস যতবার তার জন্য নির্ধারিত সীমা অতিক্রম করেছে।
processes
বর্তমানে যতগুলি প্রসেস মনিটর করা হচ্ছে।

এড়িয়ে যান

ignore সাব-কমান্ড সাময়িকভাবে নির্দিষ্ট UID বা সব প্রসেসকে মেমরি লিমিট থেকে বাদ দেয়। এটি পারফর্ম্যান্স বেঞ্চমার্কিং, স্ট্রেস টেস্টিং বা মেমরি বিহেভিয়ার ডায়াগনসিস করার জন্য উপযোগী:

# Ignore a specific UID
adb shell am memory-limiter ignore 10087
# Ignore all processes (temporarily disables limiting)
adb shell am memory-limiter ignore all
# Resume normal limiting operation
adb shell am memory-limiter ignore none

ম্যানুয়াল

manual সাব-কমান্ড, প্রসেস আইডি (PID) অনুযায়ী নির্দিষ্ট প্রসেসের জন্য গণনা করা সীমা ওভাররাইড করে এবং বাইটে কাস্টম অ্যাবসোলিউট ভ্যালু সেট করে। মানটি অবশ্যই একটি পূর্ণসংখ্যা হতে হবে, তবে MiB বোঝাতে MB প্রত্যয় বা GiB বোঝাতে GB প্রত্যয় অন্তর্ভুক্ত থাকতে পারে:

# Set a 1GiB limit for PID 1234
adb shell am memory-limiter manual 1234 1073741824
# Set a 1GiB limit for PID 1234
adb shell am memory-limiter manual 1234 1024MB
# Set a 1GiB limit for PID 1234
adb shell am memory-limiter manual 1234 1GB
# Remove the manual override for PID 1234
adb shell am memory-limiter manual 1234 none

ম্যানুয়াল ওভাররাইড শুধুমাত্র সেই নির্দিষ্ট প্রসেস ইনস্ট্যান্সের লাইফটাইমের জন্য প্রযোজ্য। প্রসেসটি আবার শুরু হলে, এটি তার স্ট্যাটাসের উপর ভিত্তি করে স্ট্যান্ডার্ড সীমায় ফিরে আসে।

ম্যানুয়াল ওভাররাইড ফিজিক্যাল সিস্টেমের সীমা অতিক্রম করতে পারে না।