স্মৃতিশক্তি হ্রাস করুন

একবার আপনি অ্যান্ড্রয়েড মেমরি ম্যানেজমেন্ট বুঝে গেলে এবং আপনার গেমের মেমরি ব্যবহার পরিমাপ করার জন্য টুলস সেট আপ করে নিলে, পরবর্তী পদক্ষেপ হলো সক্রিয়ভাবে এর ব্যবহার কমানো এবং অপ্টিমাইজ করা। অ্যান্ড্রয়েডের কঠোর সীমার মধ্যে থাকলে তা সিস্টেমকে আপনার গেম বন্ধ করা থেকে বিরত রাখতে সাহায্য করে, দীর্ঘ স্টার্টআপ সময় রোধ করে এবং নিশ্চিত করে যে আপনার গেমটি সমস্ত ডিভাইসে ভালোভাবে চলে।

এই নির্দেশিকাটি আপনার গেমের মেমরি ফুটপ্রিন্ট কমানোর জন্য কার্যকরী কৌশল প্রদান করে, বিশেষত অ্যাসেট-স্তরের অপ্টিমাইজেশন, ইঞ্জিন-নির্দিষ্ট কনফিগারেশন এবং মেমরি ব্যবস্থাপনার সর্বোত্তম অনুশীলনের উপর আলোকপাত করে।

ইউনিটিতে মেমরি হ্রাস করুন

ইউনিটির আর্কিটেকচারাল ডিজাইনের কারণে, নেটিভ ব্লক অ্যালোকেটর এবং ম্যানেজড হিপ একবার প্রসারিত হলে, অ্যাসেটগুলো রিলিজ হয়ে যাওয়ার পরেও ইঞ্জিন সেই মেমোরি পেজগুলোকে অপারেটিং সিস্টেম (OS)-এ তাৎক্ষণিকভাবে ফেরত না দিয়ে, পুনঃব্যবহারের জন্য ধরে রাখে। বিশেষত, ভার্চুয়াল অ্যাড্রেস স্পেস (রিজার্ভড মেমোরি) প্রসেসটির জীবনকাল পর্যন্ত সংরক্ষিত থাকে, এবং বেশ কয়েকটি গার্বেজ কালেকশন (GC) ও ট্রিমিং সাইকেল সম্পন্ন না হওয়া পর্যন্ত ফিজিক্যাল মেমোরি (RSS) সঙ্গে সঙ্গে পুনরুদ্ধার করা হয় না। ফলস্বরূপ, মেমোরির সাময়িক সর্বোচ্চ ব্যবহার প্রকৃত ব্যবহার কমে যাওয়ার পরেও রেসিডেন্ট মেমোরিকে দীর্ঘ সময়ের জন্য স্ফীত রাখতে পারে। এই আচরণটি লো-এন্ড ডিভাইসগুলোতে আউট-অফ-মেমোরি (OOM) ক্র্যাশের ঝুঁকি বাড়ায় এবং সার্বিক রানটাইম স্থিতিশীলতা হ্রাস করে।

অতএব, ইউনিটি মেমরি অপ্টিমাইজেশনের কাজটি অবশ্যই তিনটি মূল স্তম্ভের মাধ্যমে করতে হবে, যা এই ইঞ্জিনের আচরণগুলোর জন্য বিশেষভাবে তৈরি করা হয়েছে:

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

আরও তথ্যের জন্য, ইউনিটি মেমরি অপ্টিমাইজেশন দেখুন।

বহু-প্রক্রিয়া অপ্টিমাইজেশন

ক্যাশ করা প্রসেসগুলোর মেমরি ব্যবহার মেমরি লিমিটের হিসাব থেকে বাদ রাখা হয়, কারণ এটি সক্রিয় অ্যাপগুলোর উপর কোনো প্রভাব ফেলে না। সার্ভিসটিকে একটি আলাদা বিচ্ছিন্ন প্রসেসে চালালে মূল প্রসেসটি যত দ্রুত সম্ভব ক্যাশ করা অবস্থায় যেতে পারে, যার ফলে আপনার গেমের স্বাস্থ্য উন্নত হয়।

আরও তথ্যের জন্য, দেখুন কিভাবে প্রসেসের অবস্থা ও মেমরি ট্র্যাক করতে হয় , কিভাবে ইউনিটি দিয়ে একটি সার্ভিস প্রসেসকে আলাদা করতে হয় , এবং কিভাবে আনরিয়েল দিয়ে একটি সার্ভিস প্রসেসকে আলাদা করতে হয়

ব্যবহারকারী-অনুভূত পরিষেবাগুলিতে মেমরি ব্যবহার হ্রাস করা

আপনার গেমে বড় কোনো ডাউনলোড সম্পন্ন করা বা ব্যাকগ্রাউন্ড ভয়েস চ্যাট সিস্টেমের মতো ক্ষেত্রে ইউজার-পারসিভড সার্ভিসে লজিক চালানোর প্রয়োজন হতে পারে। এই কৌশলগুলো আপনাকে এই ধরনের পরিস্থিতিতে মেমরি ব্যবহার পরিচালনা ও কমাতে সাহায্য করতে পারে।

বড় ডাউনলোডের কৌশল

এই কৌশলগুলো বড় আকারের ডাউনলোডের ক্ষেত্রে প্রযোজ্য হতে পারে, যেগুলো ব্যবহারকারী আপনার গেমটি মিনিমাইজ করার পরেও আপনি চালিয়ে যেতে চান।

১. ডাউনলোড প্রক্রিয়াটিকে পৃথক করুন

করণীয়: একটি পৃথক প্রসেসে ডাউনলোডটি সম্পাদন করে নিশ্চিত করুন যে, আপনার অ্যাপ যে মেমরি ব্যবহার করছে না তা যেন অপারেটিং সিস্টেম (OS) অবিলম্বে পুনরুদ্ধার করতে পারে। কারণ, এমনটা হতে পারে যে মেমরি অ্যালোকেটর মেমরি পুল পেজগুলো ধরে রাখতে পারে এবং অ্যারেগুলো মুক্ত করার পরেও অ্যানোনিমাস আরএসএস (Anonymous RSS) মেমরিকে কৃত্রিমভাবে উচ্চ রাখতে পারে। যখন আপনি সার্ভিস এবং প্রসেসটি স্পষ্টভাবে বন্ধ বা এক্সিট করবেন, তখন মেমরিটি ওএস পুলে ফেরত চলে যাবে এবং আপনার মূল প্রসেসটি অক্ষত থাকবে।

  • ইউনিটিতে: একটি কাস্টম ম্যানিফেস্টে android:process=":downloader" এর মতো প্রসেস দিয়ে ঘোষিত একটি নেটিভ অ্যান্ড্রয়েড Service ডাউনলোডটি অফলোড করুন এবং ইউনিটির AndroidJavaClass JNI দিয়ে এটিকে কল করুন। ডাউনলোড সম্পূর্ণ হলে প্রসেসটি টার্মিনেট করতে ভুলবেন না। আরও বিস্তারিত নির্দেশনার জন্য 'ইউনিটিতে একটি পৃথক প্রসেসে একটি উপলব্ধিযোগ্য পরিষেবা চালান' দেখুন।

  • আনরিলে: আনরিয়েল প্লাগইন ল্যাঙ্গুয়েজ ব্যবহার করে android:process=":downloader" এর মতো একটি প্রসেস সহ একটি কাস্টম অ্যান্ড্রয়েড Service ডিক্লেয়ার করুন এবং C++ JNI দিয়ে এটিকে ট্রিগার করুন। ডাউনলোড সম্পূর্ণ হলে প্রসেসটি টার্মিনেট করতে ভুলবেন না। আরও বিস্তারিত নির্দেশনার জন্য " Run a perceptible service in a separate process with Unreal" দেখুন।

  • নেটিভ অ্যান্ড্রয়েডের জন্য: AndroidManifestandroid:process=":downloader" মতো একটি প্রসেস সহ একটি Service ডিক্লেয়ার করুন। এই আইসোলেটেড প্রসেসে ডাউনলোডটি চালান এবং ডাউনলোড সম্পূর্ণ হলে Process.killProcess(Process.myPid()) কল করুন।

এর ফলে যা হয়: এটি মেমরি দখলে থাকার সময়কাল কমিয়ে দেয় এবং বৃহত্তর মূল প্রসেস দ্বারা ব্যবহৃত মেমরি মুক্ত করার পাশাপাশি ডাউনলোড চালিয়ে যেতে সাহায্য করে।

২. ডাউনলোডগুলি সরাসরি ডিস্কে স্ট্রিম করুন

বিষয়বস্তু: নেটওয়ার্ক রেসপন্সগুলোকে একটি বড় অ্যারেতে জমা করে লেখার পরিবর্তে, একটি ছোট ও নির্দিষ্ট আকারের পুনঃব্যবহারযোগ্য বাফার ব্যবহার করে সরাসরি নেটওয়ার্ক সকেট থেকে ডিস্কে ডেটা স্ট্রিম করা।

  • ইউনিটিতে: অ্যাসেট বান্ডেল বা বড় ফাইলের জন্য DownloadHandlerBuffer ব্যবহার করা এড়িয়ে চলুন, কারণ এটি ফাইলের আকারের সমান একটি নেটিভ মেমরি বাফার (অ্যানোনিমাস আরএসএস মেমরি) বরাদ্দ করে। এর পরিবর্তে, একটি ব্যাকগ্রাউন্ড থ্রেডে নেটিভভাবে ডিস্কে বাইট স্ট্রিম করতে DownloadHandlerFile ব্যবহার করুন।

  • আনরিলে: IHttpRequest থেকে পেলোডগুলিকে TArray<uint8> -এ যুক্ত করার পরিবর্তে, SetResponseBodyReceiveStream() ব্যবহার করে আগত ডেটার খণ্ডগুলিকে সরাসরি একটি FArchive (আনরিলের ফাইল ম্যানেজার ব্যবহার করে তৈরি ফাইল-ব্যাকড আর্কাইভ)-এ পাইপ করুন।

  • নেটিভ অ্যান্ড্রয়েডের জন্য: HTTP রেসপন্সে .readBytes() বা .string() কল করার পরিবর্তে, একটি পুলড বাফার ব্যবহার করে InputStream কে FileOutputStream এ পাইপ করুন।

এটি যেভাবে সাহায্য করে: সর্বোচ্চ মেমরি ব্যবহার হ্রাস করে।

৩. স্ট্রিম ডাউনলোড করা ফাইল ডিকম্প্রেশন

করণীয়: আপনার ডাউনলোড করা ফাইলটি যদি কম্প্রেসড হয়, তবে ফাইলটি ডাউনলোড করে, র‍্যামে লোড করে, এবং তারপর এক্সট্র্যাক্ট করার পরিবর্তে, আপনার নেটওয়ার্ক ইনপুট স্ট্রিমটিকে ZipInputStream মতো কোনো স্ট্রিমিং ডিকম্প্রেসরের মধ্যে র‍্যাপ করুন।

এটি যেভাবে সাহায্য করে: সর্বোচ্চ মেমরি ব্যবহার হ্রাস করে।

৪. অপারেটিং সিস্টেমকে দায়িত্ব অর্পণ করুন

কী: ব্যাকগ্রাউন্ড মেমোরি ব্যবস্থাপনার ঝামেলা পুরোপুরি এড়াতে, এই কাজটি অ্যান্ড্রয়েডের নেটিভ এপিআই-এর ওপর অর্পণ করুন।

  • WorkManager হলো OS-স্তরের JobScheduler একটি আধুনিক ও প্রস্তাবিত র‍্যাপার। Android 14+ এর জন্য, WorkManager স্বয়ংক্রিয়ভাবে ব্যবহারকারীর দ্বারা শুরু করা ডাউনলোডগুলোকে একটি User-Initiated Data Transfer (UIDT) জব হিসেবে পরিচালনা করে। এটি আপনার অ্যাপের প্রসেসের ভেতরে চলে, তাই মেমোরির ব্যবহার কমাতে আপনাকে অবশ্যই সরাসরি ডিস্কে স্ট্রিম করতে হবে। সিস্টেম রিসোর্স সীমিত হয়ে গেলে, UIDT আপনার ডাউনলোডকে সুন্দরভাবে পজ ও রিজুম করার সুযোগ দিয়ে আপনার অ্যাপকে ‘লো মেমোরি’ ক্র্যাশ থেকে রক্ষা করে।

  • DownloadManager একটি পৃথক সিস্টেম প্রসেসে চলে এবং ডাউনলোডের জন্য ব্যবহৃত মেমরির দায় আপনার অ্যাপের উপর চাপায় না। ফাইলটি ডাউনলোড হয়ে প্রস্তুত হলে আপনার অ্যাপ একটি ব্রডকাস্ট নোটিফিকেশন পাবে।

এটি যেভাবে সাহায্য করে: WorkManager কম মেমরির পরিস্থিতি সামলাতে সাহায্য করে, এবং DownloadManager আপনার অ্যাপের মেমরি ব্যবহার কমিয়ে দেয়।

সহায়ক পরিষেবাগুলির জন্য কৌশল

এই কৌশলগুলি সেইসব সহায়ক পরিষেবার ক্ষেত্রে প্রযোজ্য হতে পারে যা একটি গেম মূল গেম প্রক্রিয়ার সমান্তরালে চালাতে চাইতে পারে, যেমন ব্যাকগ্রাউন্ড ভয়েস চ্যাট।

১. প্রক্রিয়াটিকে বিচ্ছিন্ন করুন

কী: ফিচারটিকে, যেমন আপনার ভয়েস চ্যাট সলিউশনকে, মূল গেম ইঞ্জিন থেকে আলাদা করুন। উদাহরণস্বরূপ, আপনি মাইক্রোফোন ক্যাপচার এবং নেটওয়ার্ক স্ট্রিমিং একটি অ্যান্ড্রয়েড ফোরগ্রাউন্ড সার্ভিসের ভিতরে চালাতে পারেন, যা একটি পৃথক প্রসেসে (ম্যানিফেস্টে ঘোষিত, যেমন android:process=":voice" দিয়ে) বরাদ্দ করা থাকবে।

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

২. অব্যবহৃত ইন-প্রসেস মেমরি ছাঁটাই করুন

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

  • ইউনিটিতে: যখন OnApplicationPause() চালু হয়, তখন এই ছাঁটাইটি সম্পাদন করুন। Resources.UnloadUnusedAssets() সহায়ক হতে পারে।

  • আনরিয়েলে: ট্রিমিং লজিককে ApplicationWillEnterBackgroundDelegate ডেলিগেটের সাথে বাইন্ড করুন।

  • নেটিভ অ্যান্ড্রয়েডের জন্য: প্রয়োজন অনুযায়ী onPause() বা onStop() ফাংশনে মেমরি ট্রিম করুন। বেশি মেমরি ব্যবহারকারী প্রসেসগুলো বন্ধ করার আগে, অপারেটিং সিস্টেম আপনার তৈরি করা onTrimMemory() ফাংশনটি কল করার চেষ্টা করতে পারে।

এর ফলে যা হয়: গেমটি ফোরগ্রাউন্ডে না থাকলে এটি অপ্রয়োজনীয় মেমোরি ব্যবহার কমায়।