সিস্টেম-ব্যাপী সমস্যা সমাধান

মেমরি সংক্রান্ত সমস্যা প্রায়শই পুরো সিস্টেম জুড়ে একাধিক উপাদানের সাথে জড়িত থাকে। কার্নেল কীভাবে মেমরি পরিচালনা করে এবং প্রসেসগুলো কীভাবে রিসোর্সের জন্য প্রতিযোগিতা করে, তা বোঝা জটিল সমস্যা সমাধানের জন্য অত্যন্ত গুরুত্বপূর্ণ।

সিস্টেম বিশ্লেষণের জন্য পারফেট্টো

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

  • প্রতিটি প্রসেসের জন্য প্রসেস মেমরি কাউন্টারগুলো হলো : rss.anon , rss.file এবং swap
  • কার্নেল পরিসংখ্যান : /proc/vmstat এবং /proc/meminfo থেকে প্রাপ্ত তথ্য।
  • পিএসআই (প্রেসার স্টল ইনফরমেশন) : মেমোরির চাপের কারণে কতগুলো প্রসেস আটকে আছে, তার বিস্তারিত মেট্রিক্স।
  • এলএমকে ইভেন্টস : কখন এবং কেন লো মেমোরি কিলার একটি প্রসেস বন্ধ করার সিদ্ধান্ত নেয়।
  • সময়সূচী নির্ধারণ : মেমরি পুনরুদ্ধার কার্যকলাপ ( kswapd ) এবং সিপিইউ ব্যবহারের মধ্যে সম্পর্ক স্থাপন করুন।

পারফেটোতে মেমরি কাউন্টার

ট্রেস দেখার সময়, একটি প্রসেসের ট্র্যাক গ্রুপ প্রসারিত করুন এবং বিভিন্ন ভার্চুয়াল মেমরি কাউন্টার দেখতে নিচের দিকে স্ক্রল করুন।

পারফেটটো মেমোরি কাউন্টারস, com.android.MemoryLab-এ কিছু ভার্চুয়াল মেমোরি কাউন্টার দেখাচ্ছে।

মেমরি কাউন্টারের জন্য ট্রেস কনফিগার করা

একটি ট্রেসে এই প্রতি-প্রক্রিয়া কাউন্টারগুলি ক্যাপচার করতে, আপনার পারফেটটো কনফিগারেশনে ( pbtxt ) অবশ্যই নিম্নলিখিত ডেটা উৎসগুলি অন্তর্ভুক্ত থাকতে হবে:

  1. kmem/rss_stat সহ linux.ftrace : এই ইভেন্ট-ভিত্তিক উৎসটি কার্নেল দ্বারা RSS (রেসিডেন্ট সেট সাইজ) আপডেট করার সাথে সাথে এর তাৎক্ষণিক পরিবর্তনগুলো ধারণ করে। এটি rss.anon , rss.file এবং swap জন্য উচ্চ-রেজোলিউশনের ডেটা সরবরাহ করে।

    data_sources: {
        config {
            name: "linux.ftrace"
            ftrace_config {
                ftrace_events: "kmem/rss_stat"
                # ... other events
            }
        }
    }
    
  2. linux.process_stats : এই পোল করা উৎসটি সমস্ত প্রসেসের মেমরির প্রাথমিক অবস্থা এবং পর্যায়ক্রমিক আপডেট প্রদান করে। ট্রেসের শুরুতে মেমরির পরম মান দেখার জন্য এটি অপরিহার্য।

    data_sources: {
        config {
            name: "linux.process_stats"
            process_stats_config {
                scan_all_processes_on_start: true
                proc_stats_poll_ms: 1000 # Optional periodic polling
            }
        }
    }
    

চাপ স্টল তথ্য (পিএসআই)

PSI আপনাকে জানায় যে সিস্টেম (বা কোনো নির্দিষ্ট প্রসেস) মেমরি রিসোর্সের জন্য অপেক্ষা করতে কতটা সময় ব্যয় করেছে।

  • some : অন্তত একটি প্রসেস মেমোরির জন্য অপেক্ষা করতে গিয়ে আটকে গিয়েছিল।
  • full : সমস্ত সক্রিয় প্রসেস একই সাথে থেমে গেছে। এটি একটি গুরুতর প্রতিবন্ধকতা নির্দেশ করে।

আপনি ADB-এর মাধ্যমে PSI মানগুলি পরীক্ষা করতে পারেন:

adb shell cat /proc/pressure/memory

লো মেমোরি কিলার (LMK)

সিস্টেম যখন চাপের মধ্যে থাকে, তখন মেমোরি খালি করার জন্য প্রসেস বন্ধ করার দায়িত্ব LMK-এর। আধুনিক অ্যান্ড্রয়েড সংস্করণগুলিতে, ইউজারস্পেস lmkd ডেমন logcat এ লগ করে, আর কার্নেল-স্তরের oom_kill ইভেন্টগুলি dmesg এ লগ করা হয়।

# Check userspace LMKD
adb logcat | grep -i "lmkd"

# Check kernel OOM killer
adb shell dmesg | grep -i "oom_kill"

পারফেট্টোতে, LMK ইভেন্টগুলো সিস্টেম-ব্যাপী ট্র্যাকগুলিতে মার্কার হিসেবে প্রদর্শিত হয়। প্রতিটি ইভেন্টে কিল করা প্রসেসটির PID এবং কারণ (যেমন, "ক্যাশে খুব কম") অন্তর্ভুক্ত থাকে।


কার্নেল পুনরুদ্ধার: অদলবদল এবং উচ্ছেদ

যখন সিস্টেমে খালি র‍্যাম কমে আসে, তখন কার্নেলকে নতুন অ্যালোকেশনের জন্য জায়গা খালি করার উপায় খুঁজে বের করতে হয়। এটি দুটি প্রধান পদ্ধতির মাধ্যমে এই কাজটি করে থাকে: অ্যানোনিমাস মেমরি সোয়াপিং এবং ফাইল-ব্যাকড পেজ ইভিক্টিং

বেনামী স্মৃতি এবং ZRAM

অ্যানোনিমাস মেমোরির (জাভা হিপ, নেটিভ হিপ, স্ট্যাক) স্টোরেজে কোনো অনুরূপ ফাইল থাকে না। অ্যান্ড্রয়েড এটি পরিচালনা করার জন্য ZRAM ব্যবহার করে, যা র‍্যামের মধ্যে থাকা একটি সংকুচিত সোয়াপ স্পেস।

  1. কম্প্রেশন : কার্নেল নিষ্ক্রিয় অ্যানোনিমাস পেজগুলো শনাক্ত করে এবং সেগুলোকে কম্প্রেস করে।
  2. সোয়াপ-আউট : সংকুচিত পেজগুলোকে ZRAM অঞ্চলে স্থানান্তর করা হয়।
  3. সোয়াপ-ইন : যখন কোনো প্রসেস একটি ZRAM পেজ অ্যাক্সেস করে, তখন কার্নেল সেটিকে ডিকম্প্রেস করে সাধারণ র‍্যামে ফিরিয়ে দেয়।

অ্যান্ড্রয়েডে, pswpin এবং pswpout মতো স্ট্যান্ডার্ড লিনাক্স সোয়াপ কাউন্টারগুলো বিশেষভাবে এই ZRAM কার্যকলাপ ট্র্যাক করে, কারণ ZRAM-কে প্রাথমিক (এবং সাধারণত একমাত্র) সোয়াপ ডিভাইস হিসেবে কনফিগার করা থাকে।

ZRAM-এর অবস্থা পরিদর্শন করা হচ্ছে

  • বৈশ্বিক মোট পরিমাণ : কী পরিমাণ ZRAM কনফিগার করা আছে এবং বর্তমানে কী পরিমাণ ব্যবহৃত হচ্ছে তা দেখতে /proc/meminfo ব্যবহার করুন।

    adb shell cat /proc/meminfo | grep Swap
    # Example output:
    # SwapCached:          0 kB
    # SwapTotal:     2097148 kB
    # SwapFree:      1850244 kB
    

    SwapTotal হলো ZRAM ডিভাইসের মোট আকার। SwapTotal - SwapFree হলো বর্তমানে ZRAM-এ সংরক্ষিত সংকুচিত ডেটার পরিমাণ।

  • কম্প্রেশন রেশিও : কম্প্রেশন কতটা কার্যকর তা দেখতে, ডেটার আসল আকারের সাথে ZRAM ডিভাইসে এর সংকুচিত আকারের তুলনা করুন।

    # Original (uncompressed) size of stored data
    adb shell cat /sys/block/zram0/orig_data_size
    # 524288000 (500 MB)
    
    # Compressed size of stored data
    adb shell cat /sys/block/zram0/compr_data_size
    # 104857600 (100 MB)
    

    এই কাল্পনিক উদাহরণে, ডেটা ৫:১ অনুপাতে সংকুচিত করা হয়েছে। প্রকৃত সংকোচন অনুপাত অসংকুচিত ডেটার এনট্রপির উপর নির্ভর করে।

  • ফিজিক্যাল র‍্যাম ওভারহেড : ZRAM নিজেই কম্প্রেসড ব্লকগুলো পরিচালনা করার জন্য র‍্যাম ব্যবহার করে।

    adb shell cat /sys/block/zram0/mem_used_total
    # 115343360 (110 MB)
    

    এটি হলো ZRAM ডিভাইসটি বর্তমানে যে পরিমাণ ফিজিক্যাল র‍্যাম ব্যবহার করছে তার প্রকৃত পরিমাণ (কম্প্রেসড ডেটা + মেটাডেটা)।

অনুশীলন: ZRAM কম্প্রেশন অনুপাত

এই অনুশীলনে, আপনি পর্যবেক্ষণ করবেন কীভাবে বিভিন্ন ধরণের ডেটা ZRAM-এর কার্যকারিতাকে প্রভাবিত করে, যা আপনাকে বাস্তব অ্যাপের মেমরি বিশ্লেষণ করার সময় কী আশা করা উচিত সে সম্পর্কে একটি ধারণা তৈরি করতে সাহায্য করবে।

  1. প্রস্তুতি : নিশ্চিত করুন যে মেমোরিল্যাব চালু আছে। ‘ফ্রি অল অ্যালোকেশনস’- এ ট্যাপ করুন।
  2. বেসলাইন : mm_stat এ বর্তমান ZRAM পরিসংখ্যান লক্ষ্য করুন :

    adb shell cat /sys/block/zram0/mm_stat
    # Columns: orig_data_size, compr_data_size, mem_used_total, ...
    
  3. র‍্যান্ডম ডেটা (~১x অনুপাত) : নেটিভ মেমরি (১জিবি ইনকম্প্রেসিবল) বরাদ্দ করুন। সোয়াপ-আউটের জন্য অপেক্ষা করুন ( vmstat চেক করুন অথবা ১০ সেকেন্ড অপেক্ষা করুন)।

    • পর্যবেক্ষণ : আপনি দেখবেন orig_data_size এবং compr_data_size প্রায় একই পরিমাণে বৃদ্ধি পাচ্ছে। র‍্যান্ডম ডেটার এনট্রপি বেশি এবং একে কম্প্রেস করা যায় না। এটিই হলো সবচেয়ে খারাপ পরিস্থিতি।
  4. সবগুলো ১ (~৪ গুণ অনুপাত) : ‘Free All Allocations’- এ ট্যাপ করুন, তারপর ‘Allocate Native (1GB Ones)’ ( 0xFF )-এ ট্যাপ করুন।

    • পর্যবেক্ষণ : compr_data_size মাত্র প্রায় ২৫০ মেগাবাইট বৃদ্ধি পাবে। এটি কম্প্রেশনের জন্য একটি আদর্শ পরিস্থিতি। অ্যালগরিদমটি (সাধারণত LZO বা LZ4) সহজেই পুনরাবৃত্তিমূলক প্যাটার্নটি শনাক্ত করে।
  5. সবগুলো ০ (>১০০x অনুপাত) : ‘Free All Allocations’- এ ট্যাপ করুন, তারপর ‘Allocate Native (1GB Zeros) ( 0x00 )-এ ট্যাপ করুন।

    • পর্যবেক্ষণ : আপনি অসংকুচিত এবং সংকুচিত ডেটার একটি অস্বাভাবিকভাবে উচ্চ অনুপাত দেখতে পাবেন। orig_data_size ১ জিবি বেড়ে যায়, কিন্তু compr_data_size এবং mem_used_total প্রায় অপরিবর্তিত থাকে।
    • ‘রহস্য’ : এটি কম্প্রেশন নয়, এটি একটি কার্নেল শর্টকাট। ZRAM ব্যাকএন্ড ( zsmalloc ) শূন্য দিয়ে পূর্ণ পেজ শনাক্ত করে এবং কম্প্রেশন এড়িয়ে যায়। এর পরিবর্তে, এটি পেজটিকে গ্লোবাল জিরো পেজ- এর একটি ডুপ্লিকেট হিসেবে চিহ্নিত করে, যার জন্য মাত্র কয়েক বাইট মেটাডেটা ব্যবহৃত হয়।

ZRAM-এর সাধারণ নিয়মাবলী

একটি বাস্তব সিস্টেম বিশ্লেষণ করার সময়, আপনি নিম্নলিখিত সাধারণ কম্প্রেশন অনুপাতগুলো আশা করতে পারেন। এই অনুমানগুলো একটি আদর্শ ৪কেবি পেজ সাইজ ধরে নেওয়া হয়েছে এবং এতে ZRAM-এর মেমরি ব্যবস্থাপনার ওভারহেড বিবেচনা করা হয়েছে:

ডেটা টাইপ সাধারণ অনুপাত কারণ
শূন্য পৃষ্ঠা ১০০ গুণের বেশি কার্নেল 'জিরো পেজ' শর্টকাটের মাধ্যমে অপ্টিমাইজ করা হয়েছে (কম্প্রেসার এড়িয়ে যায়)।
ধ্রুবক পৃষ্ঠাগুলি ~৪x পুনরাবৃত্ত মান (যেমন, 0xFF ) নিখুঁতভাবে সংকুচিত হয়, কিন্তু প্রতি-পৃষ্ঠার ওভারহেড এবং স্ল্যাব অ্যালাইনমেন্ট কার্যকর অনুপাতকে সীমিত করে।
টেক্সট / JSON / লগ ~২.৫ গুণ থেকে ~৩.৫ গুণ উচ্চ রিডানডেন্সি, কিন্তু একটিমাত্র পুনরাবৃত্ত বাইটের চেয়ে উচ্চতর এনট্রপি।
জাভা হিপ ~২x থেকে ~৩x সদৃশ হেডার এবং বিক্ষিপ্ত ফিল্ডযুক্ত অনেকগুলো ছোট অবজেক্ট।
মেশিন কোড (DEX/নেটিভ) ~১.৫ গুণ থেকে ~২ গুণ নির্দেশনাগুলো জটিল হলেও সেগুলোর মধ্যে চেনা যায় এমন কিছু ধরন রয়েছে।
ডিকোড করা বিটম্যাপ (ইউআই) ~২x থেকে ~৩x বড় সমতল রঙিন এলাকা (আইকন, ব্যাকগ্রাউন্ড) থাকলে এটি কার্যকর।
ডিকোড করা বিটম্যাপ (ছবি) ~১.১x থেকে ~১.২x অত্যধিক এনট্রপি; পিক্সেলের মানগুলো অনেক বেশি পরিবর্তিত হয়।
এনক্রিপ্টেড/সংকুচিত ডেটা ~১x ইতিমধ্যে উচ্চ এনট্রপি সম্পন্ন; ZRAM আর সংকুচিত করতে পারে না।

এই কারণেই আমরা আমাদের প্রাথমিক মেমরি প্রেসার অনুশীলনের জন্য র‍্যান্ডম ডেটা ব্যবহার করি: এটি কম্প্রেশনের জন্য সবচেয়ে খারাপ পরিস্থিতি, কারণ এই ডেটার এনট্রপি সর্বোচ্চ থাকে, তাই এই পেজগুলোকে ZRAM-এ সোয়াপ করলেও RAM-এর মোট আকার বাড়ে না এবং ফলস্বরূপ অন্য যেকোনো ডেটার চেয়ে দ্রুত ফিজিক্যাল মেমরি প্রেসার তৈরি করে।

পেজক্যাশ উচ্ছেদ

ফাইল-ভিত্তিক মেমরি (DEX, লাইব্রেরি, অ্যাসেট) পেজ ক্যাশের মাধ্যমে পরিচালিত হয়।

  • ক্লিন পেজ : যে পেজগুলো স্টোরেজের ডেটার সাথে মিলে যায়। কার্নেল এগুলোকে তাৎক্ষণিকভাবে বাদ (এভিক্ট) দিতে পারে।
  • ডার্টি পেজ (Dirty Pages) : র‍্যামে পরিবর্তিত কিন্তু এখনো স্টোরেজে লেখা হয়নি এমন পেজ। এগুলো লেখা না হওয়া পর্যন্ত ড্রপ করা যায় না।

পেজক্যাশের অবস্থা পরিদর্শন করা হচ্ছে

  • বৈশ্বিক মোট : /proc/meminfo দেখায় পেজ ক্যাশে কী পরিমাণ মেমরি বরাদ্দ করা হয়েছে।

    adb shell cat /proc/meminfo | grep -E "^(Cached|Active\(file\)|Inactive\(file\))"
    # Example output:
    # Cached:          1234567 kB
    # Active(file):     456789 kB
    # Inactive(file):   777778 kB
    

    কার্নেল প্রথমে Inactive(file) পেজগুলোকে অপসারণ করতে পছন্দ করে। যদি Active(file) Inactive(file) চেয়ে উল্লেখযোগ্যভাবে বড় হয়, তবে এটি ইঙ্গিত দেয় যে পেজ ক্যাশের বেশিরভাগ অংশ সক্রিয়ভাবে ব্যবহৃত হচ্ছে।

  • ক্রমবর্ধমান ত্রুটি : সিস্টেমকে স্টোরেজ থেকে কতবার পেজ লোড করতে হয়েছে তা পর্যবেক্ষণ করুন।

    adb shell cat /proc/vmstat | grep -E "pgfault|pgmajfault"
    # Example output:
    # pgfault 12345678    # Total page faults (including minor/re-faults)
    # pgmajfault 1234     # Major faults (actually required disk I/O)
    

    "মেমরি থ্র্যাশিং" হলো এমন একটি অবস্থা যখন কোড এক্সিকিউট করে ব্যবহারকারীর কাঙ্ক্ষিত লক্ষ্যের দিকে অগ্রসর হওয়ার পরিবর্তে, র‍্যামের মধ্যে ও বাইরে পেজ অদলবদল করতেই উল্লেখযোগ্য পরিমাণ সময় ব্যয় হয়। দ্রুত বাড়তে থাকা pgmajfault কাউন্টার থ্র্যাশিংয়ের একটি জোরালো সূচক।

vmstat দিয়ে রানটাইম কার্যকলাপ

রিয়েল-টাইমে অদলবদল এবং উচ্ছেদ হতে দেখতে, vmstat ব্যবহার করুন।

adb shell vmstat 1
# Example output:
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
#  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
#  1  0 246904 123456  12345 800000    0    0   120     0 1234 5678  5  2 92  1  0

কার্যকলাপের জন্য মূল কলামগুলি:

  • si / so : ZRAM থেকে সোয়াপ-ইন এবং সোয়াপ-আউট। এখানে অশূন্য মানের অর্থ হলো কার্নেল সক্রিয়ভাবে সংকুচিত স্টোরেজে অ্যানোনিমাস পেজ স্থানান্তর করছে।
  • bi / bo : ব্লক-ইন এবং ব্লক-আউট (I/O)। মেমরি চাপের সময় উচ্চ bi ঘন ঘন পেজ ক্যাশে রি-ফল্ট (থ্র্যাশিং) নির্দেশ করে।
  • wa (I/O wait) : ডিস্ক I/O-এর জন্য অপেক্ষা করার সময় সিপিইউ-এর নিষ্ক্রিয় থাকার সময়ের শতাংশ। উচ্চ wa হলো পারফরম্যান্সের আকস্মিক আকস্মিক পতনের (performance "cliff") বাস্তব রূপ।

kswapd এবং সরাসরি পুনরুদ্ধার

kswapd হলো একটি কার্নেল থ্রেড যা ব্যাকগ্রাউন্ডে মেমরি পুনরুদ্ধার করার চেষ্টা করে, যখন মুক্ত মেমরির পরিমাণ একটি নির্দিষ্ট সীমার নিচে নেমে আসে।

  • kswapd উচ্চ সিপিইউ ব্যবহার : এটি নির্দেশ করে যে সিস্টেমটি খালি পৃষ্ঠা খুঁজে পেতে ক্রমাগত চেষ্টা করছে।
  • ডাইরেক্ট রিক্লেইম : যদি kswapd তাল মেলাতে না পারে, তাহলে প্রসেসগুলো তাদের নিজেদের অ্যালোকেশনের কাজ শুরু করার আগে সিনক্রোনাসভাবে মেমোরি রিক্লেইম করতে বাধ্য হয়। এটি পারফেটোতে "ডাইরেক্ট রিক্লেইম" ইভেন্ট হিসেবে দেখা যায়।

থ্র্যাশিং এবং রি-ফল্ট

যখন কার্নেল এমন কোনো পেজকে সরিয়ে দেয় যা তখনও সক্রিয়ভাবে ব্যবহৃত হচ্ছে, তখন একটি "রি-ফল্ট" ঘটে। যদি সিস্টেম ক্রমাগত একই পেজগুলোকে সরিয়ে দেয় এবং সাথে সাথেই আবার লোড করে, তবে তাকে থ্র্যাশিং বলা হয়।

থ্র্যাশিংয়ের ফলে উচ্চ I/O ওয়েট ( top বা vmstat মতো টুলে wa ) দেখা যায়। I/O ওয়েট হলো সেই সময়ের শতাংশ, যা একটি অসমাপ্ত ডিস্ক I/O অপারেশন (যেমন একটি ইভিক্টেড DEX পেজ পুনরায় লোড করা) সম্পূর্ণ হওয়ার জন্য অপেক্ষা করার সময় সিপিইউ নিষ্ক্রিয় থাকে। উচ্চ wa এর কারণে মোট সিপিইউ ব্যবহার কম দেখালেও ডিভাইসটি প্রতিক্রিয়াহীন বলে মনে হয়।

সিস্টেম টিউনিং: অদলবদল

swappiness প্যারামিটারটি নির্ধারণ করে যে কার্নেল অ্যানোনিমাস মেমরি সোয়াপ আউট করতে পছন্দ করবে, নাকি ফাইল-ব্যাকড মেমরি ইভিক্ট করবে।

adb shell cat /proc/sys/vm/swappiness
  • পরিসর : আধুনিক লিনাক্স কার্নেলগুলিতে (৫.৮+) এর পরিসর হলো ০ থেকে ২০০
    • : কার্নেল শুধুমাত্র চরম জরুরি অবস্থায় সোয়াপ করবে।
    • ১০০ : কার্নেল অ্যানোনিমাস এবং ফাইল-ব্যাকড মেমরিকে সমানভাবে বিবেচনা করে।
    • ২০০ : কার্নেল যতটা সম্ভব ফাইল-সমর্থিত মেমরি (পেজ ক্যাশে) র‍্যামে রাখার জন্য অ্যানোনিমাস মেমরিকে ZRAM-এ সোয়াপ করতে জোরালোভাবে পছন্দ করে।
  • অ্যান্ড্রয়েডের সাধারণ মান : বেশিরভাগ অ্যান্ড্রয়েড-চালিত ডিভাইস উচ্চ সোয়াপিনেস (swappiness) দিয়ে টিউন করা থাকে, যা সাধারণত ১০০ থেকে ১৬০- এর মধ্যে থাকে (কিছু ক্ষেত্রে এমনকি ২০০- ও ব্যবহৃত হয়)। এর কারণ হলো, ZRAM সোয়াপ সাধারণত UFS বা eMMC স্টোরেজ থেকে পেজ রিড করার চেয়ে দ্রুততর হয়, এবং অ্যাপ ও সিস্টেম কোড এবং ডেটার জন্য পেজ ক্যাশে সংরক্ষণ করা অ্যাপ চালুর পারফরম্যান্স এবং সামগ্রিক সিস্টেম রেসপন্সিভনেসের জন্য অত্যন্ত গুরুত্বপূর্ণ। এর বিপরীতে, লিনাক্স ডেস্কটপ এবং সার্ভার মেশিনে সাধারণ সেটিং থাকে ৬০ , কারণ এই মেশিনগুলিতে পারসিস্টেন্ট স্টোরেজ সাধারণত দ্রুততর হয়।

হাতে-কলমে অনুশীলন: পেজ ফল্ট, পেজ ক্যাশে, এবং সোয়াপ

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

১. ডিভাইসটি প্রস্তুত করুন

আপনার ডিভাইস বা এমুলেটরের রুট অ্যাক্সেস আছে কিনা তা নিশ্চিত করুন ( adb root )।

অ্যাপটি চালু করুন এবং একটি বড় টেস্ট ফাইল (যেমন, ৫০০ মেগাবাইট) তৈরি করুন, যা আমরা পরে ম্যাপ করব:

  1. ওপেন মেমোরিল্যাব
  2. টেস্ট ফাইল তৈরি করুন (৫০০ এমবি) -এ ট্যাপ করুন।

লগগুলিতে কাজ সম্পন্ন হওয়ার সংকেত পাওয়া পর্যন্ত অপেক্ষা করুন।

২. শনাক্তকরণের জন্য প্রস্তুতি নিন।

স্টোরেজ থেকে ফাইলটি লোড হতে দেখা নিশ্চিত করতে, আমাদের বিদ্যমান পেজ ক্যাশে পরিষ্কার করতে হবে।

# Stop the app to release its existing mappings
adb shell am force-stop com.android.memorylab

# Drop all clean caches
adb shell "echo 3 > /proc/sys/vm/drop_caches"

৩. একটি পারফেটটো ট্রেস রেকর্ড করুন।

এমন একটি কনফিগারেশন ব্যবহার করুন যা vmstat কাউন্টার এবং পেজ ক্যাশ ইভেন্টগুলো ক্যাপচার করে।

vmstat কাউন্টার এবং পেজ ক্যাশ ইভেন্টগুলি ক্যাপচার করে একটি ব্যাকগ্রাউন্ড পারফেটটো ট্রেস শুরু করুন:

adb shell perfetto -c - --txt \
  -o /data/misc/perfetto-traces/swap_exercise.perfetto-trace --background <<EOF
buffers: { size_kb: 131072 }
data_sources: {
    config {
        name: "linux.sys_stats"
        sys_stats_config { vmstat_period_ms: 250 }
    }
}
duration_ms: 60000
EOF

৪. স্মৃতিতে চাপ সৃষ্টি করা

  1. মেমোরিল্যাব চালু করুন।
  2. Mmap thrash_test.bin (৫০০ মেগাবাইট ফাইল-সমর্থিত) ট্যাপ করুন। এটি আমাদের কাস্টম ফাইলটিকে ম্যাপ করে।
  3. ‘Allocate Native Memory (1GB Incompressible)’ বোতামটি বেশ কয়েকবার ট্যাপ করুন। ডিভাইসটি ধীরগতির মনে না হওয়া পর্যন্ত এটি চালিয়ে যান। এর ফলে কার্নেল অ্যানোনিমাস মেমরিকে ZRAM-এ সোয়াপ করতে এবং অবশেষে ক্যাশ থেকে আমাদের ম্যাপ করা ফাইলটিকে বের করে দিতে বাধ্য হয়।
  4. থ্র্যাশ পেজক্যাশ (রিফল্ট টেস্ট) ট্যাপ করুন। এটি ম্যাপ করা ফাইলটি বারবার পড়ে, এবং যদি ফাইলটি ইভিক্ট করা হয়ে থাকে তবে রি-ফল্ট ঘটাতে বাধ্য করে।

5. Perfetto মধ্যে ট্রেস বিশ্লেষণ

ui.perfetto.dev- এ ট্রেসটি খুলুন।

ত্রুটিগুলো পর্যবেক্ষণ করুন এবং অদলবদল করুন

Memory গ্রুপটি খুঁজুন, তারপর vmstat গ্রুপটি এক্সপ্যান্ড করুন। এই গ্রুপটিতে বিভিন্ন কার্নেল-লেভেল কাউন্টার রয়েছে, যেগুলো পুরো সিস্টেম জুড়ে মেমরি ম্যানেজমেন্ট কার্যকলাপের হিসাব রাখে।

পারফেট্টো ভিএমস্ট্যাট কাউন্টার দেখাচ্ছে

আপনি যে ট্র্যাকগুলি দেখছেন সেগুলি কার্নেলের মেমরি অবস্থার বিভিন্ন দিক তুলে ধরে:

  • মেমরি স্টেট কাউন্টার (পরম মান) : এই ট্র্যাকগুলি একটি নির্দিষ্ট অবস্থায় থাকা মেমরির বর্তমান পরিমাণ দেখায়। স্ক্রিনশটে, এগুলি পরম মান হিসাবে প্রদর্শিত হয় (যেমন, কিলোবাইট বা পেজের সংখ্যায়)।

    • nr_free_pages : ফিজিক্যাল র‍্যামের যে অংশ সম্পূর্ণ খালি থাকে।
    • nr_active_anon / nr_inactive_anon : অ্যানোনিমাস মেমরি (যেমন হিপ এবং স্ট্যাক) যা বর্তমানে ব্যবহৃত হচ্ছে (সক্রিয়) অথবা কিছু সময় ধরে অ্যাক্সেস করা হয়নি (নিষ্ক্রিয়)। কার্নেল প্রথমে নিষ্ক্রিয় পেজগুলোকে সোয়াপ আউট করতে পছন্দ করে।
    • nr_active_file / nr_inactive_file : ফাইল-সমর্থিত মেমরি (পেজ ক্যাশে) যা সক্রিয় বা নিষ্ক্রিয়। নিষ্ক্রিয় ফাইল পেজগুলোই উচ্ছেদের জন্য প্রথম প্রার্থী।
  • অ্যাক্টিভিটি কাউন্টার (রেট) : যে কাউন্টারগুলো সময়ের সাথে সাথে মোট ইভেন্টের সংখ্যা দেখায়, যেমন পেজ ফল্ট এবং সোয়াপ অপারেশন, সেগুলোর ক্ষেত্রে ক্রমবর্ধমান মোট সংখ্যার চেয়ে ইভেন্টের হার দেখা প্রায়শই বেশি উপযোগী হয়। পারফেটটো UI-তে, আপনি একটি কাউন্টার ট্র্যাকের উপর কার্সর নিয়ে গিয়ে, মেট্রিক আইকনে ক্লিক করে, তারপর মোডে ক্লিক করে ভ্যালু , ডেল্টা বা রেট-এর মধ্যে থেকে বেছে নিতে পারেন। রেট ভিউ অ্যাক্টিভিটির আকস্মিক বৃদ্ধি চিহ্নিত করা এবং সেগুলোকে অন্যান্য সিস্টেম ইভেন্টের সাথে সম্পর্কযুক্ত করা অনেক সহজ করে তোলে।

    • pswpout (সোয়াপ আউট) : যে হারে অ্যানোনিমাস পেজগুলোকে কম্প্রেস করে ZRAM- এ স্থানান্তর করা হচ্ছে। এর উচ্চ স্পাইক তীব্র মেমোরি চাপ নির্দেশ করে।
    • pswpin (সোয়াপ ইন) : যে হারে প্রসেসগুলো পূর্বে ZRAM-এ স্থানান্তরিত পেজগুলোকে পুনরায় রিড করে।
    • pgfault (মোট পেজ ফল্ট) : সমস্ত পেজ ফল্টের হার, যার মধ্যে ডিস্ক I/O ছাড়াই সমাধান করা ফল্টগুলোও (ছোটখাটো ফল্ট) অন্তর্ভুক্ত।
    • pgmajfault (মেজর পেজ ফল্ট) : সেইসব ফল্টের হার, যা মেটাতে ডিস্ক I/O-এর প্রয়োজন হয় (যেমন, স্টোরেজ থেকে ইভিক্টেড কোড পুনরায় লোড করা)। এটি থ্র্যাশিং- এর একটি প্রধান সূচক।

আপনি স্ক্রিনশটে লক্ষ্য করবেন যে, যখন nr_free_pages উল্লেখযোগ্যভাবে কমে যায়, তখন pswpout এ অনুরূপ স্পাইক দেখা যায়, কারণ কার্নেল র‍্যাম খালি করার জন্য তাড়াহুড়ো করে। পরবর্তীতে, যখন আমরা পেজ ক্যাশে "থ্র্যাশ" করি, তখন pgmajfault এবং nr_active_file এ স্পাইক দেখা যায়।

পৃষ্ঠা ক্যাশে উচ্ছেদ পর্যবেক্ষণ করুন

পারফেটোতে পেজ ক্যাশ ইভেন্ট খুঁজে পেতে: ১. সার্চ বারে mm_filemap_add_to_page_cache টাইপ করুন। ২. ইভেন্টগুলো Ftrace ইভেন্টস ট্র্যাকে স্লাইস হিসেবে দেখা যাবে (প্রতিটি CPU-এর জন্য একটি ট্র্যাক)। ৩. MemoryLab প্রসেসটি এক্সপ্যান্ড করুন। যদি ftrace সঠিকভাবে কনফিগার করা থাকে, তাহলে আপনি প্রসেসটির থ্রেডগুলোর সাথে সম্পর্কিত ফাইলম্যাপ অ্যাক্টিভিটি দেখতে পাবেন।

পারফেট্টো ftrace-এ পেজ ক্যাশে ইভেন্টগুলি দেখাচ্ছে

  • mm_filemap_add_to_page_cache : পেজ ক্যাশে একটি পেজ যোগ করা নির্দেশ করে।
  • mm_filemap_delete_from_page_cache : নির্দেশ করে যে একটি পৃষ্ঠা ক্যাশে থেকে বহিষ্কৃত করা হয়েছে।
  • mm_filemap_fault : এটি নির্দেশ করে যে একটি মেমরি-ম্যাপড ফাইলে পেজ ফল্ট ঘটেছে।

ত্রুটিগুলোকে প্রথমে ইনোড-এ, তারপর ফাইল-এ সমাধান করা হচ্ছে।

যেকোনো একটি add_to_page_cache ইভেন্টে ক্লিক করুন। Details প্যানেলে, i_ino (আইনোড নম্বর) খুঁজুন। এটি নির্দিষ্ট ফাইলটিকে শনাক্ত করে।

একটি স্বতন্ত্র add_to_page_cache ইভেন্ট i_ino দেখাচ্ছে

আপনি ম্যানুয়ালি একটি আইনোডকে ফাইল পাথে রূপান্তর করতে পারেন:

# Replace <INODE_NUMBER> with the value from Perfetto
adb shell find /system /data /apex /data/user/0 -inum <INODE_NUMBER>

কার্যকরী স্ক্রিপ্ট: ব্যাচ পদ্ধতিতে ইনোড সমাধান করা

আপনার যদি অনেকগুলো ইভেন্ট থাকে, তাহলে আপনি ট্রেস থেকে সমস্ত অনন্য ইনোড বের করতে একটি PerfettoSQL কোয়েরি ব্যবহার করতে পারেন এবং একটি হেল্পার স্ক্রিপ্টের সাহায্যে সেগুলোকে স্বয়ংক্রিয়ভাবে সমাধান করতে পারেন।

  1. ইনোড নিষ্কাশন করুন : অনন্য i_ino মানগুলি পেতে trace_processor ব্যবহার করুন:

    ./trace_processor -Q "SELECT DISTINCT int_value FROM args t JOIN raw r ON r.arg_set_id = t.arg_set_id WHERE r.name = 'mm_filemap_add_to_page_cache' AND t.key = 'i_ino'" \
      trace.perfetto-trace > inodes.txt
    
  2. সমাধান করুন : একটি দ্রুত শেল লুপের মাধ্যমে সরাসরি আপনার টার্মিনাল থেকে ইনোডগুলি সমাধান করুন:

    while read -r inode; do
      echo "Inode $inode -> $(adb shell find /system /data /apex /data/user/0 \
          -maxdepth 4 -inum "$inode" 2>/dev/null)"
    done < inodes.txt
    

পিক্সেল 10a থেকে প্রাপ্ত আউটপুটের উদাহরণ:

Resolving 10 unique inodes for device localhost:27198...
Inode 14051 -> /data/user/0/com.android.memorylab/files/thrash_test.bin
Inode 1382 -> /system/framework/framework.jar
Inode 203 -> /system/bin/cmd
Inode 17998 -> /data/misc/logd/logcat

← পরিষেবা সংযুক্তি | ↑ উপরে | পুনরুদ্ধার →