কম্পিউটার টিউটোরিয়াল

রুবি মেমরি লিকস বোঝা এবং ঠিক করা:একটি ব্যাপক গাইড

মেমরি লিক নিয়ে এই দুই পর্বের সিরিজের প্রথম অংশে, আমরা দেখেছি কিভাবে রুবি মেমরি পরিচালনা করে এবং কিভাবে গারবেজ কালেকশন (GC) কাজ করে।

আপনি আরও মেমরি সহ শক্তিশালী মেশিনগুলি বহন করতে সক্ষম হতে পারেন এবং আপনার অ্যাপটি প্রায়শই পুনঃসূচনা হতে পারে যা আপনার ব্যবহারকারীরা লক্ষ্য করবেন না, তবে মেমরি ব্যবহার গুরুত্বপূর্ণ।

বরাদ্দ এবং আবর্জনা সংগ্রহ বিনামূল্যে নয়। যদি আপনার একটি লিক থাকে, তাহলে আপনি যা করার জন্য আপনার অ্যাপটি তৈরি করেছেন তা করার পরিবর্তে আপনি আবর্জনা সংগ্রহে আরও বেশি সময় ব্যয় করেন৷

এই পোস্টে, আমরা মেমরি লিক আবিষ্কার এবং নির্ণয় করতে আপনি যে সরঞ্জামগুলি ব্যবহার করতে পারেন সেগুলি আরও গভীরভাবে দেখব৷

চলুন চালিয়ে যাই!

রুবিতে লিক খোঁজা

একটি ফাঁস সনাক্ত করা যথেষ্ট সহজ। আপনি GC ব্যবহার করতে পারেন , ObjectSpace ,এবং আপনার APM টুলে RSS গ্রাফগুলি আপনার মেমরির ব্যবহার বৃদ্ধি দেখার জন্য। কিন্তু আপনার একটি ফুটো আছে জেনে এটি ঠিক করার জন্য যথেষ্ট নয়। এটি কোথা থেকে আসছে তা আপনাকে জানতে হবে। কাঁচা সংখ্যা আপনাকে তা বলতে পারে না।

সৌভাগ্যবশত, রুবি ইকোসিস্টেমে সেই সংখ্যাগুলির সাথে প্রসঙ্গ সংযুক্ত করার জন্য কিছু দুর্দান্ত সরঞ্জাম রয়েছে। দুটি হল memory-profiler এবং derailed_benchmarks .

memory_profiler রুবিতে

memory_profiler রত্ন একটি খুব সাধারণ API এবং একটি বিশদ (যদিও সামান্য অপ্রতিরোধ্য) বরাদ্দ করা এবং ধরে রাখা মেমরি রিপোর্ট প্রদান করে — এতে বরাদ্দ করা বস্তুর ক্লাস, তাদের আকার এবং কোথায় সেগুলি বরাদ্দ করা হয়েছে তা অন্তর্ভুক্ত করে৷ আমাদের ফাঁস হওয়া প্রোগ্রামে যোগ করা সহজ৷

 

এটির অনুরূপ একটি প্রতিবেদন আউটপুট করা হচ্ছে৷

 

এখানে অনেক তথ্য আছে, কিন্তু সাধারণত, allocated objects by location এবং retained objects by location ফাঁস খুঁজতে গেলে বিভাগগুলি সবচেয়ে কার্যকর হতে পারে। এই ফাইলের অবস্থান যা বস্তু বরাদ্দ করে, বরাদ্দকৃত বস্তুর সংখ্যা অনুসারে।

  • allocated অবজেক্ট হল report এর মধ্যে বরাদ্দ করা (সৃষ্টি করা) সমস্ত বস্তু ব্লক।
  • retained অবজেক্ট হল এমন বস্তু যেগুলি report শেষ না হওয়া পর্যন্ত আবর্জনা সংগ্রহ করা হয়নি ব্লক আমরা ব্লকের শেষের আগে একটি GC চালাতে বাধ্য করেছি যাতে আমরা ফাঁস হওয়া বস্তুগুলিকে আরও স্পষ্টভাবে দেখতে পারি।

retained বিশ্বাস করার বিষয়ে সতর্ক থাকুন বস্তু গণনা লিকিং কোডের কোন অংশ report এর মধ্যে রয়েছে তার উপর তারা অনেকটাই নির্ভর করে ব্লক।

উদাহরণস্বরূপ, যদি আমরা an_array-এর ঘোষণা স্থানান্তর করি report-এ ব্লক করুন, আমরা ভাবতে পারি যে কোডটি ফাঁস নয়।

 

ফলাফলের প্রতিবেদনের শীর্ষে অনেকগুলি রক্ষিত বস্তুর রিপোর্ট করা হবে না (শুধু রিপোর্ট নিজেই)।

 

derailed_benchmarks রুবিতে

derailed_benchmarks রত্ন হল সমস্ত ধরনের পারফরম্যান্স কাজের জন্য খুব দরকারী টুলগুলির একটি স্যুট, প্রাথমিকভাবে Rails অ্যাপের লক্ষ্য। ফাঁস খুঁজে বের করার জন্য, আমরা perf:mem_over_time দেখতে চাই , perf:objects , এবংperf:heap_diff .

এই কাজগুলি curl পাঠিয়ে কাজ করে একটি চলমান অ্যাপে অনুরোধ করে, তাই আমরা সেগুলিকে আমাদের ছোট্ট লিকি প্রোগ্রামে যুক্ত করতে পারি না। পরিবর্তে, আমাদের একটি এন্ডপয়েন্ট সহ একটি ছোট রেল অ্যাপ সেট আপ করতে হবে যা মেমরি ফাঁস করে, তারপর derailed_benchmarks ইনস্টল করুন সেই অ্যাপে।

 
 

আপনি এখন bin/rails s দিয়ে অ্যাপটি বুট করতে সক্ষম হবেন . আপনি curl করতে পারবেন একটি শেষ বিন্দু যা প্রতিটি অনুরোধে লিক হয়।

 

আমরা এখন derailed_benchmarks ব্যবহার করতে পারি আমাদের লিক অ্যাকশন দেখতে।

perf:mem_over_time

এটি আমাদের সময়ের সাথে মেমরির ব্যবহার দেখাবে (একইভাবে আমরা watch দিয়ে আমাদের লিকি স্ক্রিপ্টের থিমরি বৃদ্ধি দেখেছি। এবং ps )।

লাইনচ্যুত অ্যাপটিকে প্রোডাকশন মোডে বুট করবে, বারবার একটি এন্ডপয়েন্টে আঘাত করবে(/ ডিফল্টরূপে), এবং মেমরি ব্যবহারের প্রতিবেদন করুন। যদি এটি কখনই বৃদ্ধি না পায়, তাহলে আমাদের একটি ফুটো আছে!

 

দ্রষ্টব্য :Derailed পরীক্ষা সঞ্চালনের জন্য উত্পাদন মোডে Rails অ্যাপ বুট করবে। ডিফল্টরূপে, এটি require rails/allও করবে প্রথম যেহেতু আমাদের এই অ্যাপে কোনো ডাটাবেস নেই, তাই আমাদের এই আচরণটিকে DERAILED_SKIP_ACTIVE_RECORD=true দিয়ে ওভাররাইড করতে হবে .

কোনটি (ifany) ফাঁস হয়েছে তা দেখতে আমরা এই মানদণ্ডটি বিভিন্ন এন্ডপয়েন্টের বিরুদ্ধে চালাতে পারি।

perf:objects

perf:objects টাস্ক memory_profiler ব্যবহার করে হুডের নিচে যাতে উত্পাদিত প্রতিবেদনটি পরিচিত দেখায়।

 

এই প্রতিবেদনটি আপনার ফাঁস হওয়া মেমরি কোথায় বরাদ্দ করা হচ্ছে তা সংকুচিত করতে সহায়তা করতে পারে। আমাদের উদাহরণে, রিপোর্টের শেষ বিভাগ —Retained String Report — আমাদের সমস্যা ঠিক কী তা আমাদের বলে৷

 

আমরা LeaksController থেকে "ABC" ধারণকারী 10,000 স্ট্রিং ফাঁস করেছি অনলাইন 3. একটি নন-তুচ্ছ অ্যাপে, এই প্রতিবেদনটি উল্লেখযোগ্যভাবে বড় হবে এবং এতে রক্ষিত স্ট্রিং থাকবে যা আপনি ধরে রাখতে চান — ক্যোয়ারী ক্যাশে, ইত্যাদি — তবে এটি এবং অন্যান্য 'অবস্থান অনুসারে' বিভাগগুলি আপনাকে আপনার লিক কমাতে সাহায্য করবে৷

perf:heap_diff

perf:heap_diff বেঞ্চমার্ক সাহায্য করতে পারে যদি perf:objects থেকে রিপোর্ট আসে আপনার লিক কোথা থেকে আসছে তা দেখতে খুবই জটিল৷

নাম অনুসারে, perf:heap_diff থ্রি হিপ ডাম্প তৈরি করে এবং তাদের মধ্যে পার্থক্য গণনা করে। এটি একটি প্রতিবেদন তৈরি করে যাতে ডাম্প এবং অবস্থানের মধ্যে রাখা বস্তুর ধরন অন্তর্ভুক্ত থাকে যা তাদের বরাদ্দ করেছে।

 

আপনি 2021 সালে একটি রুবি মেমরি লিক ট্র্যাক করাও পড়তে পারেন৷ কি ঘটছে তা আরও ভালভাবে বুঝতে।

প্রতিবেদনটি আমাদেরকে নির্দেশ করে যে আমাদের ফুটো শিশুর অ্যাপের জন্য আমাদের কোথায় যেতে হবে। পার্থক্যের শীর্ষে, আমরা LeaksController থেকে 999991টি ধরে রাখা স্ট্রিং অবজেক্ট বরাদ্দ দেখি। লাইন 3.

রিয়েল রুবি এবং রেল অ্যাপে লিকস

আশা করি, আমরা এখন পর্যন্ত যে উদাহরণগুলি ব্যবহার করেছি তা বাস্তব-জীবনের অ্যাপগুলিতে কখনও রাখা হয়নি — আমি আশা করি কেউ মেমরি ফাঁস করতে চায় না!

অ-তুচ্ছ অ্যাপগুলিতে, মেমরিলিকগুলি ট্র্যাক করা অনেক কঠিন হতে পারে। রক্ষিত বস্তু সবসময় খারাপ হয় না — আবর্জনা সংগ্রহ করা আইটেম সহ একটি ক্যাশে খুব একটা কাজে আসবে না।

যদিও সমস্ত ফাঁসের মধ্যে কিছু সাধারণ আছে। কোথাও, একটি রুট-লেভেল অবজেক্ট (একটি ক্লাস/গ্লোবাল, ইত্যাদি) একটি বস্তুর একটি রেফারেন্স ধারণ করে।

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

নিম্নলিখিত কোডটি বিবেচনা করুন যা একটি গেমের জন্য একটি উচ্চ স্কোর নিয়ে আসে। এটা আমি অতীতে দেখেছি এমন কিছুর মতো। এটি একটি ব্যয়বহুল অনুরোধ, এবং যখন এটি পরিবর্তন হয় তখন আমরা সহজেই ক্যাশে বাস্ট করতে পারি, তাই আমরা এটি ক্যাশে করতে চাই৷

 

@scores হ্যাশ সম্পূর্ণরূপে আনচেক করা হয়. এটি প্রতিটি ব্যবহারকারীর জন্য প্রতিটি একক উচ্চ স্কোর ধরে রাখতে হবে — যদি আপনার কাছে অনেক কিছু থাকে তাহলে এটি আদর্শ নয়৷

একটি Rails অ্যাপে, আমরা সম্ভবত Rails.cache ব্যবহার করতে চাই এর পরিবর্তে একটি সংবেদনশীল মেয়াদ শেষ হয়ে গেছে (রেডিসে একটি মেমরি লিক এখনও একটি মেমরি লিক!)।

একটি নন-রেইলস অ্যাপে, আমরা হ্যাশের আকার সীমিত করতে চাই, সম্প্রতি ব্যবহৃত সবচেয়ে পুরনো আইটেমগুলিকে উচ্ছেদ করতে চাই৷ LruRedux একটি চমৎকার বাস্তবায়ন।

এই ফাঁসের একটি আরও সূক্ষ্ম সংস্করণ হল একটি সীমা সহ একটি ক্যাশে, কিন্তু যার কীগুলি নির্বিচারে আকারের। যদি চাবি নিজেই বড় হয়, তাই ক্যাশেও হবে। সাধারণত, আপনি এই আঘাত করা হবে না. কিন্তু, আপনি যদি বস্তুগুলিকে JSON হিসেবে সিরিয়ালাইজ করে থাকেন এবং সেটিকে একটি কী হিসেবে ব্যবহার করেন, তাহলে দুবার চেক করুন যে আপনি এমন জিনিসগুলিকে সিরিয়ালাইজ করছেন না যা ব্যবহারের সাথে বৃদ্ধি পাচ্ছে — যেমন ব্যবহারকারীর পঠিত বার্তাগুলির একটি তালিকা৷

সার্কুলার রেফারেন্স

সার্কুলার রেফারেন্স পারি আবর্জনা সংগ্রহ করা রুবিতে আবর্জনা সংগ্রহ "মার্ক এবং সুইপ" অ্যালগরিদম ব্যবহার করে। পরিবর্তনশীল প্রস্থ বরাদ্দের প্রবর্তন করার সময়, পিটার ঝু এবং ম্যাট ভ্যালেন্টাইন-হাউস এই অ্যালগরিদম কীভাবে কাজ করে তার একটি চমৎকার ব্যাখ্যা দিয়েছেন।

মূলত, দুটি পর্যায় রয়েছে:চিহ্নিতকরণ এবং ঝাড়ু দেওয়া।

  • মার্কিং-এ ফেজ, আবর্জনা সংগ্রাহক মূল বস্তু (শ্রেণী, গ্লোবাল, ইত্যাদি) থেকে শুরু করে, তাদের চিহ্নিত করে এবং তারপর তাদের রেফারেন্স বিষয়বস্তু দেখে।

    এটি তারপরে উল্লেখ করা সমস্ত বস্তুকে চিহ্নিত করে। উল্লেখিত বস্তু যেগুলি ইতিমধ্যে চিহ্নিত করা হয়েছে তা আবার দেখা হয় না। এটি চলতে থাকে যতক্ষণ না দেখার জন্য আর কোন বস্তু না থাকে — অর্থাৎ, সমস্ত উল্লেখিত বস্তু চিহ্নিত করা হয়েছে।

  • আবর্জনা সংগ্রহকারী তারপর ঝাড়ু দেওয়ার দিকে চলে যায়৷ পর্যায় চিহ্নিত না করা কোনো বস্তু পরিষ্কার করা হয়।

অতএব, লাইভ রেফারেন্স সহ বস্তুগুলি এখনও পরিষ্কার করা যেতে পারে। যতক্ষণ পর্যন্ত একটি মূল বস্তু অবশেষে একটি বস্তুর উল্লেখ না করে, এটি সংগ্রহ করা হবে। এইভাবে, বৃত্তাকার রেফারেন্স সহ বস্তুর ক্লাস্টারগুলি এখনও আবর্জনা সংগ্রহ করা যেতে পারে।

অ্যাপ্লিকেশন পারফরম্যান্স মনিটরিং:ইভেন্ট টাইমলাইন এবং বরাদ্দকৃত বস্তুর গ্রাফ

এই সিরিজের প্রথম অংশে উল্লিখিত হিসাবে, যেকোন প্রোডাকশন-লেভেল অ্যাপের কিছু ফর্ম অ্যাপ্লিকেশন পারফরম্যান্স মনিটরিং (APM) ব্যবহার করা উচিত।

অনেকগুলি বিকল্প উপলব্ধ, যার মধ্যে আপনার নিজের রোল করা (শুধুমাত্র বড় দলগুলির জন্য প্রস্তাবিত)। একটি APM থেকে আপনার পাওয়া একটি মূল বৈশিষ্ট্য হল একটি অ্যাকশন (বা ব্যাকগ্রাউন্ড জব) যে পরিমাণ বরাদ্দ করে তা দেখার ক্ষমতা। ভালো APMtools এটিকে ভেঙে দেবে, কোথা থেকে বরাদ্দ আসে — কন্ট্রোলার, ভিউ ইত্যাদির অন্তর্দৃষ্টি দেয়।

এটিকে প্রায়ই 'ইভেন্ট টাইমলাইন' এর মতো কিছু বলা হয়। বোনাস পয়েন্ট যদি আপনার এপিএম আপনাকে কাস্টম কোড লিখতে দেয় যা টাইমলাইনকে আরও ভেঙে দেয়।

একটি রেল কন্ট্রোলার জন্য নিম্নলিখিত কোড বিবেচনা করুন.

 

একটি APM দ্বারা রিপোর্ট করা হলে, 'ইভেন্ট টাইমলাইন' অ্যাপসিগন্যাল থেকে নিম্নলিখিত স্ক্রিনশটের মতো দেখতে হতে পারে৷

রুবি মেমরি লিকস বোঝা এবং ঠিক করা:একটি ব্যাপক গাইড

এটিকে ইনস্ট্রুমেন্ট করা যেতে পারে যাতে আমরা দেখতে পারি কোডের কোন অংশটি টাইমলাইনে বরাদ্দ করে। বাস্তব অ্যাপে, এটি সম্ভবত কোড থেকে কম স্পষ্ট হবে 😅

 

এখানে একটি ইন্সট্রুমেন্টেড ইভেন্ট টাইমলাইনের উদাহরণ, আবার AppSignal থেকে:

রুবি মেমরি লিকস বোঝা এবং ঠিক করা:একটি ব্যাপক গাইড

কোথায় যন্ত্র করতে হবে তা জানা প্রায়শই বোঝা কঠিন হতে পারে। সত্যিই আপনার অ্যাপ্লিকেশনের কোড বোঝার জন্য কোন বিকল্প নেই, কিন্তু কিছু সংকেত আছে যা 'গন্ধ' হিসেবে কাজ করতে পারে।

আপনার APM যদি সময়ের সাথে GC রান বা বরাদ্দের উপর সারফেস করে, আপনি স্পাইকগুলি দেখতে পারেন যে সেগুলি কিছু নির্দিষ্ট প্রান্তে আঘাত করা বা কিছু চলমান ব্যাকগ্রাউন্ড কাজের সাথে মিলে যায় কিনা। এখানে AppSignal এর Ruby VM ম্যাজিক ড্যাশবোর্ড থেকে আরেকটি উদাহরণ দেওয়া হল:

রুবি মেমরি লিকস বোঝা এবং ঠিক করা:একটি ব্যাপক গাইড

এইভাবে বরাদ্দের দিকে তাকিয়ে, আমরা মেমরি সমস্যাগুলির দিকে নজর দেওয়ার সময় আমাদের অনুসন্ধানকে সংকুচিত করতে পারি। এটি memory_profiler এর মতো সরঞ্জামগুলি ব্যবহার করা আরও সহজ করে তোলে এবং derailed_benchmarks দক্ষতার সাথে।

AppSignal এর রুবি রত্ন, যেমন বরাদ্দ এবং GC পরিসংখ্যান ট্র্যাকিং এর সর্বশেষ সংযোজন সম্পর্কে পড়ুন।

র্যাপিং আপ

এই পোস্টে, আমরা memory_profiler সহ মেমরির ফাঁস খুঁজে পেতে এবং ঠিক করতে সাহায্য করতে পারে এমন কিছু সরঞ্জামগুলিতে ডুব দিয়েছি , derailed_benchmarks , perf:mem_over_time , perf:objects , perf:heap_diff , অ্যাপসিগন্যালে ইভেন্টের টাইমলাইন এবং বরাদ্দকৃত বস্তুর গ্রাফ।

আমি আশা করি আপনি প্রথম অংশের পাশাপাশি এই পোস্টটি খুঁজে পেয়েছেন, আপনার রুবি অ্যাপে মেমরি লিক নির্ণয় এবং বাছাই করতে কার্যকর৷

আমরা যে সরঞ্জামগুলি ব্যবহার করেছি সে সম্পর্কে আরও পড়ুন:

  • memory_profiler
  • derailed_benchmarks
  • লিকি রেল অ্যাপ

অতিরিক্ত বিস্তারিত পড়া:

  • GC মডিউল ডকুমেন্টেশন
  • ObjectSpace মডিউল ডকুমেন্টেশন
  • গর্বেজ কালেকশন ডিপ ডাইভ
  • পরিবর্তনশীল প্রস্থ বরাদ্দ

শুভ কোডিং!

পি.এস. আপনি যদি রুবি ম্যাজিক পোস্টগুলি প্রেস থেকে বের হওয়ার সাথে সাথে পড়তে চান তবে আমাদের রুবি ম্যাজিক নিউজলেটারে সাবস্ক্রাইব করুন এবং একটি পোস্ট মিস করবেন না!


  1. 6টি সেরা ওয়ার্ডপ্রেস ফায়ারওয়াল প্লাগইন (তুলনা করা)

  2. দুটি BST থেকে জোড়া গণনা করুন যার যোগফল C++ এ একটি প্রদত্ত মানের x এর সমান

  3. অ্যাসিম্পোটিক বিশ্লেষণ

  4. প্লট দেখানোর জন্য কখন plt.Show() প্রয়োজন এবং কখন তা নয়?