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

অ্যান্ড্রয়েড ১৭ এবং এর পরবর্তী সংস্করণগুলোতে মেমোরি লিমিটার অন্তর্ভুক্ত রয়েছে। এটি একটি সিস্টেম সার্ভিস যা লিনাক্স সিগ্রুপ ভি২ (Linux cgroup v2) ব্যবহার করে অ্যাপ্লিকেশন প্রসেসগুলোর মেমোরি ব্যবহার পর্যবেক্ষণ ও সীমিত করে। মেমোরি লিমিটার কোনো একক অ্যাপকে অসামঞ্জস্যপূর্ণ সিস্টেম মেমোরি ব্যবহার করা থেকে বিরত রাখে, যা সামগ্রিক মেমোরির উপর চাপ কমায় এবং গুরুত্বপূর্ণ ফোরগ্রাউন্ড ও ক্যাশড প্রসেসগুলোকে মেমোরির স্বল্পতার কারণে হঠাৎ বন্ধ করে দেওয়া থেকে রক্ষা করে।

প্রক্রিয়া

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

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

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

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

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

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

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

প্রক্রিয়া পর্যবেক্ষণ

মেমরি লিমিটার ডিফল্টরূপে অ্যাপ প্রসেসগুলোকে (UID >= 10000) মনিটর করে। সিস্টেমের অপরিহার্য স্থিতিশীলতা বজায় রাখার জন্য কোর সিস্টেম প্রসেসগুলোকে এর আওতামুক্ত রাখা হয়।

মেমরি লিমিটার প্রসেসের ভিজিবিলিটি স্টেটের উপর ভিত্তি করে মেমরি লিমিট নির্ধারণ করে:

  • দৃশ্যমান প্রসেস: যে প্রসেসগুলো ব্যবহারকারীর কাছে দৃশ্যমান কোনো 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 সীমা অতিক্রম করে, তখন মেমরি লিমিটার ঘটনাটি শনাক্ত করে এবং ডায়াগনস্টিক পদক্ষেপ নিতে পারে, যেমন মেমরি প্রোফাইল ক্যাপচার করা বা statsd এ কোনো অস্বাভাবিকতা লগ করা।

কনফিগারেশন

মেমরি লিমিটার তার কনফিগারেশন vendor পার্টিশন থেকে পড়ে নেয়:

  • ফাইলের পথ: /vendor/etc/memory-limiter-config.xml

XML ফরম্যাট

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

<MemoryLimiterConfig>
  <version>1</version>
  <configList>
    <!-- RAM minimums account for MemTotal excluding carve-outs. -->
    <limitSet>
      <!-- Limits for 16GB RAM device (MemTotal >= 15GiB): 10G/5G/5G/5G -->
      <minimumRequiredMemTotal>15360</minimumRequiredMemTotal>
      <memVisible>10240</memVisible>
      <memNotVisible>5120</memNotVisible>
      <swapVisible>5120</swapVisible>
      <swapNotVisible>5120</swapNotVisible>
    </limitSet>
    <limitSet>
      <!-- Limits for 12GB RAM device (MemTotal >= 11GiB): 8G/4G/4G/4G -->
      <minimumRequiredMemTotal>11264</minimumRequiredMemTotal>
      <memVisible>8192</memVisible>
      <memNotVisible>4096</memNotVisible>
      <swapVisible>4096</swapVisible>
      <swapNotVisible>4096</swapNotVisible>
    </limitSet>
    <limitSet>
      <!-- Limits for 8GB RAM device (MemTotal >= 7GiB): 5G/3G/3G/3G -->
      <minimumRequiredMemTotal>7168</minimumRequiredMemTotal>
      <memVisible>5120</memVisible>
      <memNotVisible>3072</memNotVisible>
      <swapVisible>3072</swapVisible>
      <swapNotVisible>3072</swapNotVisible>
    </limitSet>
    <limitSet>
      <!-- Limits for 6GB RAM device (MemTotal >= 5GiB): 4G/2G/2G/2G -->
      <minimumRequiredMemTotal>5120</minimumRequiredMemTotal>
      <memVisible>4096</memVisible>
      <memNotVisible>2048</memNotVisible>
      <swapVisible>2048</swapVisible>
      <swapNotVisible>2048</swapNotVisible>
    </limitSet>
    <limitSet>
      <!-- Limits for 4GB RAM device (MemTotal >= 3GiB): 2G/1G/1G/1G -->
      <minimumRequiredMemTotal>3072</minimumRequiredMemTotal>
      <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 থ্রেশহোল্ডগুলোতে এই কার্ভ-আউটগুলোর জন্য একটি মার্জিন অন্তর্ভুক্ত থাকে। উদাহরণস্বরূপ, ১৬ জিবি ডিভাইসকে লক্ষ্য করে তৈরি একটি কনফিগারেশনে minimumRequiredMemTotal হিসেবে 15360 (16 GiB)-এর পরিবর্তে 16384 (15 GiB) নির্দিষ্ট করা হয়, এবং ১২ জিবি ডিভাইসের জন্য একটি টিয়ারে 11264 (11 GiB) নির্দিষ্ট করা হয়। এটি নিশ্চিত করে যে বোর্ড-স্তরের কার্ভ-আউটের ভিন্নতা নির্বিশেষে প্রতিটি ডিভাইস তার উদ্দিষ্ট টিয়ারের সাথে মেলে।

memVisible

দৃশ্যমান প্রসেসগুলিতে প্রযোজ্য সফট মেমোরি লিমিট ( memory.high ) MiB এককে।

memNotVisible

অদৃশ্য প্রসেসগুলোর ক্ষেত্রে সফট মেমোরি লিমিট ( memory.high ) MiB এককে প্রয়োগ করা হয়।

swapVisible

দৃশ্যমান প্রসেসগুলিতে প্রযোজ্য সোয়াপ স্পেসের সীমা ( memory.swap.max ) MiB এককে।

swapNotVisible

অদৃশ্য প্রসেসগুলোর ক্ষেত্রে সোয়াপ স্পেসের সীমা ( memory.swap.max ) MiB এককে প্রযোজ্য।

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

অ্যান্ড্রয়েড ১৭ এবং এর পরবর্তী সংস্করণগুলিতে, প্ল্যাটফর্মটি /vendor/etc/memory-limiter-config.xml ফাইলে সাধারণ ফিজিক্যাল র‍্যাম স্তরগুলি জুড়ে স্ট্যান্ডার্ড মেমরি এবং সোয়াপ সীমা নির্দিষ্ট করে দেয়:

ফিজিক্যাল র‍্যাম ন্যূনতম প্রয়োজনীয়
মেমটোটাল
(ন্যূনতম প্রয়োজনীয় মোট সদস্য সংখ্যা)
দৃশ্যমান মেমরি সীমা
(মেমভিজিবল)
দৃশ্যমান নয় মেমরি সীমা
(মেমটি দৃশ্যমান নয়)
দৃশ্যমান অদলবদল সীমা
(অদলবদল দৃশ্যমান)
অদৃশ্য অদলবদল সীমা
(swapNotVisible)
১৬ জিবি ১৫,৩৬০ এমআইবি (১৫ জিআইবি) ১০,২৪০ এমআইবি (১০ জিআইবি) ৫,১২০ এমআইবি (৫ জিআইবি) ৫,১২০ এমআইবি (৫ জিআইবি) ৫,১২০ এমআইবি (৫ জিআইবি)
১২ জিবি ১১,২৬৪ এমআইবি (১১ জিআইবি) ৮,১৯২ এমআইবি (৮ জিআইবি) ৪,০৯৬ এমআইবি (৪ জিআইবি) ৪,০৯৬ এমআইবি (৪ জিআইবি) ৪,০৯৬ এমআইবি (৪ জিআইবি)
৮ জিবি ৭,১৬৮ এমআইবি (৭ জিআইবি) ৫,১২০ এমআইবি (৫ জিআইবি) ৩,০৭২ এমআইবি (৩ জিআইবি) ৩,০৭২ এমআইবি (৩ জিআইবি) ৩,০৭২ এমআইবি (৩ জিআইবি)
৬ জিবি ৫,১২০ এমআইবি (৫ জিআইবি) ৪,০৯৬ এমআইবি (৪ জিআইবি) ২,০৪৮ এমআইবি (২ জিআইবি) ২,০৪৮ এমআইবি (২ জিআইবি) ২,০৪৮ এমআইবি (২ জিআইবি)
৪ জিবি ৩,০৭২ এমআইবি (৩ জিআইবি) ২,০৪৮ এমআইবি (২ জিআইবি) ১,০২৪ এমআইবি (১ জিআইবি) ১,০২৪ এমআইবি (১ জিআইবি) ১,০২৪ এমআইবি (১ জিআইবি)

স্মৃতি সীমাবদ্ধতার নীতিগুলি

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

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

  • আনুপাতিক সম্পদ বরাদ্দ: প্ল্যাটফর্মের সীমা ভৌত র‍্যামের ধারণক্ষমতা অনুযায়ী ক্রমাঙ্কিত করা হয়:

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

  • রানটাইম কোয়েরি এপিআই-এর অনুপস্থিতি: অ্যান্ড্রয়েড ১৭ এবং তার পরবর্তী সংস্করণগুলিতে, অ্যাপগুলি রান টাইমে প্রোগ্রাম্যাটিকভাবে তাদের জন্য বরাদ্দকৃত মেমরি সীমা জানতে পারে না। প্ল্যাটফর্মের স্ট্যান্ডার্ড সীমাগুলি যথেষ্ট মার্জিন সহ সংজ্ঞায়িত করা হয়েছে, যাতে সুশৃঙ্খল অ্যাপগুলি সাধারণ ব্যবহারের সময় কোনো বাধা ছাড়াই কাজ করতে পারে।

  • কার্নেল রিক্লেইম এবং সোয়াপ ডায়নামিক্স: যখন কোনো অ্যাপ প্রসেস তার memory.high সীমার কাছাকাছি পৌঁছায়, তখন লিনাক্স কার্নেল বিশেষভাবে সেই প্রসেস সি-গ্রুপকে লক্ষ্য করে মেমরি রিক্লেইম পরিচালনা করে। এর মধ্যে নিষ্ক্রিয় ফাইল-ব্যাকড পেজগুলো বাদ দেওয়া এবং কোল্ড অ্যানোনিমাস পেজগুলোকে 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

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

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