কম্পিউটার

রুবিতে ব্যবহারিক আবর্জনা সংগ্রহের টিউনিং

আমরা আবিষ্কার করেছি যে নীচের পোস্টটি 2017-এর Nate Berkopec-এর একটি নিবন্ধের উপর ভিত্তি করে তৈরি করা হয়েছে যার নাম 'GC.stat এর মাধ্যমে রুবি GC বোঝা'। মনে হচ্ছে এই নিবন্ধের কিছু অংশ চুরি করা হয়েছে, যা মূল লেখক উল্লেখ না করা পর্যন্ত আমরা অজানা ছিলাম। আমরা প্রকাশ করার আগে একটি চুরির টুলের মাধ্যমে আমাদের সমস্ত নিবন্ধ চালাই, কিন্তু এটি এটি গ্রহণ করেনি। এই অনিচ্ছাকৃত ত্রুটির জন্য আমরা Nate এবং আমাদের পাঠকদের কাছে বিশাল ক্ষমাপ্রার্থী৷

আপনার অ্যাপের পারফরম্যান্সের সম্পূর্ণ নিয়ন্ত্রণে থাকার জন্য রুবিতে আবর্জনা সংগ্রহ কীভাবে কাজ করে তা আপনার বোঝা অত্যাবশ্যক৷

এই পোস্টে, আমরা রুবিতে আবর্জনা সংগ্রহকে কীভাবে বাস্তবায়ন এবং কাস্টমাইজ করতে হয় তা নিয়ে আলোচনা করব।

চলুন চলুন!

রুবি গারবেজ কালেক্টর মডিউল

রুবি গারবেজ কালেক্টর মডিউল হল রুবির মার্ক এবং সুইপ আবর্জনা সংগ্রহের প্রক্রিয়ার একটি ইন্টারফেস।

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

এই মডিউলের সবচেয়ে বেশি ব্যবহৃত কিছু পদ্ধতি হল:

  • start/garbage_collect :এই পদ্ধতিটি ম্যানুয়ালি আবর্জনা সংগ্রহের চক্র শুরু করে।
  • সক্ষম/অক্ষম করুন৷ :এই পদ্ধতিগুলি স্বয়ংক্রিয় আবর্জনা সংগ্রহ চক্র সক্রিয় বা নিষ্ক্রিয় করে৷ অপারেশন সফল হয়েছে কিনা তা নির্দেশ করে তারা একটি বুলিয়ান মান ফেরত দেয়।
  • stat :এই পদ্ধতিটি কী এবং মানগুলির একটি তালিকা প্রদান করে যা GC মডিউলের কর্মক্ষমতা বর্ণনা করে। আমরা পরবর্তী বিভাগে এই মেট্রিক্সগুলি বিস্তারিতভাবে দেখব।

রুবি গারবেজ কালেক্টর প্যারামিটার বোঝা

রুবির জিসি কীভাবে অভ্যন্তরীণভাবে কাজ করে তা বোঝার জন্য, আসুন জিসি মডিউলের মেট্রিক্স দেখি। একটি নতুন বুট করা irb-এ নিম্নলিখিত কমান্ডটি চালান:

puts GC.stat

আপনি লক্ষ্য করবেন যে আপনার স্ক্রিনে একগুচ্ছ সংখ্যা পপ আপ হচ্ছে, এইরকম কিছু দেখাচ্ছে:

{
    :count=>12,
    :heap_allocated_pages=>49,
    :heap_sorted_length=>49,
    :heap_allocatable_pages=>0,
    :heap_available_slots=>19975,
    :heap_live_slots=>19099,
    :heap_free_slots=>876,
    :heap_final_slots=>0,
    :heap_marked_slots=>16659,
    :heap_eden_pages=>49,
    :heap_tomb_pages=>0,
    :total_allocated_pages=>49,
    :total_freed_pages=>0,
    :total_allocated_objects=>66358,
    :total_freed_objects=>47259,
    :malloc_increase_bytes=>16216,
    :malloc_increase_bytes_limit=>16777216,
    :minor_gc_count=>10,
    :major_gc_count=>2,
    :remembered_wb_unprotected_objects=>191,
    :remembered_wb_unprotected_objects_limit=>312,
    :old_objects=>16024,
    :old_objects_limit=>23556,
    :oldmalloc_increase_bytes=>158824,
    :oldmalloc_increase_bytes_limit=>16777216
}

এটি রানটাইমে কীভাবে আবর্জনা সংগ্রহ করছে সে সম্পর্কে সমস্ত তথ্য ধারণ করে। আসুন এই সংখ্যাগুলির প্রতিটি বিস্তারিতভাবে পরীক্ষা করি।

রুবি গারবেজ কালেক্টরে গণনা করা হয়

আমরা এই কীগুলি বর্ণনা করে শুরু করব:

{
    :count=>12,
    #…
    :minor_gc_count=>10,
    :major_gc_count=>2,
}

এগুলি GC গণনা, এবং তারা বেশ সহজবোধ্য তথ্য প্রদান করে। minor_gc_count এবং major_gc_count প্রতিটি ধরনের আবর্জনা সংগ্রহ চালানোর গণনা।

রুবিতে দুই ধরনের আবর্জনা সংগ্রহ করা হয়।

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

অন্যদিকে, প্রধান GC হল একটি আবর্জনা সংগ্রহের প্রচেষ্টা যা সমস্ত বস্তুকে আবর্জনা সংগ্রহ করার চেষ্টা করে, এমনকি যেগুলি তিনটি আবর্জনা সংগ্রহের চক্রের বেশি টিকে আছে। count হল minor_gc_count এর সমষ্টি এবং major_gc_count .

GC গণনা ট্র্যাক করা কয়েকটি কারণে সহায়ক হতে পারে। একটি নির্দিষ্ট কাজ বা প্রক্রিয়া সর্বদা GC গুলিকে ট্রিগার করে এবং কতবার এটি ট্রিগার করে তা আপনি বের করতে পারেন৷ মাল্টিথ্রেডেড অ্যাপ্লিকেশনের মতো ক্ষেত্রে এটি 100% সঠিক নাও হতে পারে, তবে আপনার স্মৃতিতে কোথায় রক্তপাত হচ্ছে তা বের করার জন্য এটি একটি ভাল সূচনা বিন্দু৷

হিপ নম্বর:স্লট এবং পৃষ্ঠাগুলি

এর পরে, আসুন এই কীগুলি সম্পর্কে কথা বলি, যা হিপ নম্বর নামেও পরিচিত :

{
    # page numbers
    :heap_allocated_pages=>49,
    :heap_sorted_length=>49,
    :heap_allocatable_pages=>0,
 
    # slots
    :heap_available_slots=>19975,
    :heap_live_slots=>19099,
    :heap_free_slots=>876,
    :heap_final_slots=>0,
    :heap_marked_slots=>16659,
 
    # Eden and Tomb pages
    :heap_eden_pages=>49,
    :heap_tomb_pages=>0,
}

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

  • heap_allocated_pages বর্তমানে বরাদ্দ করা হিপ পৃষ্ঠার সংখ্যা। এই পৃষ্ঠাগুলি সম্পূর্ণ খালি, সম্পূর্ণ ভরা বা আংশিকভাবে ভরাট হতে পারে।
  • heap_sorted_length প্রকৃত আকার যা হিপ মেমরিতে দখল করেছে এবং heap_allocated_pages থেকে আলাদা , যেহেতু দৈর্ঘ্য হল দৈর্ঘ্য গাদা পৃষ্ঠাগুলির একত্রিত করা, তাদের গণনা নয় . আপনি যদি প্রাথমিকভাবে 10টি পৃষ্ঠা বরাদ্দ করেন এবং তারপর সেটের মাঝখান থেকে একটি মুক্ত করেন, আপনার heap_allocated_pages 9 হবে, কিন্তু heap_sorted_length এখনও 10 হবে।
  • অবশেষে, heap_allocatable_pages বর্তমানে রুবির মালিকানাধীন স্তূপের সংখ্যা যা প্রয়োজনের সময় ব্যবহার করা যেতে পারে।

এখন, স্লটে আসছি:

  • heap_available_slots হিপ পৃষ্ঠাগুলিতে উপলব্ধ স্লটের মোট সংখ্যা৷
  • heap_live_slots মেমরিতে লাইভ বস্তুর সংখ্যা।
  • heap_free_slots বরাদ্দ করা হিপ পৃষ্ঠাগুলির স্লটগুলি খালি৷
  • heap_final_slots হল স্লটের গণনা যার বস্তুর ফাইনালাইজার আছে তাদের সাথে সংযুক্ত। ফাইনালিজারগুলি হল প্রোকস যা কোনও বস্তুকে মুক্ত করা হলে চলে, একইভাবে OOPS-এ ধ্বংসকারীর মতো৷
  • heap_marked_slots হল পুরানো বস্তুর গণনা (অর্থাৎ, 3টিরও বেশি GC চক্রের কাছাকাছি থাকা বস্তু) এবং লিখতে বাধা অরক্ষিত বস্তু৷

তারপর আমাদের tomb_pages আছে এবং eden_pages .

tomb_pages কোনো জীবন্ত বস্তু নেই এমন পৃষ্ঠাগুলির গণনা। এই পৃষ্ঠাগুলি অবশেষে রুবি দ্বারা অপারেটিং সিস্টেমে ফিরে আসে৷

অন্যদিকে, eden_pages অন্তত একটি লাইভ অবজেক্ট ধারণ করে সেই পৃষ্ঠাগুলির গণনা, তাই সেগুলি অপারেটিং সিস্টেমে ছেড়ে দেওয়া যাবে না৷

heap_free_slots মেট্রিক পর্যবেক্ষণ করার কথা বিবেচনা করুন আপনি যদি আপনার অ্যাপ্লিকেশনে মেমরি ব্লট সমস্যার সম্মুখীন হন।

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

ক্রমিক সংখ্যা

{
    :total_allocated_pages=>49,
    :total_freed_pages=>0,
    :total_allocated_objects=>66358,
    :total_freed_objects=>47259,
}

এই সংখ্যাগুলি প্রক্রিয়াটির সমগ্র জীবনের জন্য প্রকৃতিতে ক্রমবর্ধমান বা সংযোজক। তারা GC দ্বারা পুনরায় সেট করা হয় না এবং প্রযুক্তিগতভাবে নিচে যেতে পারে না। এই চারটি সংখ্যাই স্ব-ব্যাখ্যামূলক।

আবর্জনা সংগ্রহের থ্রেশহোল্ড

এই সংখ্যাগুলি বোঝার জন্য, আপনাকে প্রথমে বুঝতে হবে কখন GC ট্রিগার হয়:

{
    :malloc_increase_bytes=>16216,
    :malloc_increase_bytes_limit=>16777216,
    :remembered_wb_unprotected_objects=>191,
    :remembered_wb_unprotected_objects_limit=>312,
    :old_objects=>16024,
    :old_objects_limit=>23556,
    :oldmalloc_increase_bytes=>158824,
    :oldmalloc_increase_bytes_limit=>16777216
}

একটি সাধারণ ধারণার বিপরীতে যে GC রানগুলি নির্দিষ্ট ব্যবধানে ঘটে, রুবি যখন মেমরির স্থান ফুরিয়ে যায় তখন GC রান ট্রিগার হয়। যখন রুবি free_slots ফুরিয়ে যায় তখন ছোট GC হয় .

যদি রুবি এখনও free_slots এ কম থাকে একটি ছোট GC রানের পরে — বা oldmalloc, malloc, পুরানো বস্তুর সংখ্যা, বা ছায়াময়-এর থ্রেশহোল্ড /write-barrier-unprotected কাউন্ট অতিক্রম করেছে — একটি বড় GC রান ট্রিগার হয়েছে। gc.stat এর উপরের অংশটি এই থ্রেশহোল্ডের মান দেখায়।

malloc_increase_bytes হিপ এর বাইরে বরাদ্দ করা মেমরির পরিমাণ বোঝায় আমরা এ পর্যন্ত কথা বলেছি। যখন একটি বস্তুর আকার একটি মেমরি স্লটের স্ট্যান্ডার্ড আকারকে অতিক্রম করে — বলুন, 40 বাইট — রুবি malloc শুধু সেই বস্তুর জন্য অন্য কোথাও কিছু স্থান। যখন মোট অতিরিক্ত বরাদ্দ করা স্থান malloc_increase_bytes_limit ছাড়িয়ে যায় , একটি বড় GC ট্রিগার হয়৷

oldmalloc_increase_bytes পুরানো বস্তুর জন্য একটি অনুরূপ থ্রেশহোল্ড. old_objects পুরানো হিসাবে চিহ্নিত অবজেক্ট স্লটের একটি গণনা। যখন সংখ্যাটি old_objects_limit অতিক্রম করে , প্রধান GC ট্রিগার হয়।

remembered_wb_unprotected_objects লেখা-বাধা দ্বারা সুরক্ষিত নয় এমন বস্তুর মোট গণনা এবং মনে রাখা সেটের একটি অংশ৷ .

রাইট-ব্যারিয়ার হল রুবি রানটাইম এবং এর অবজেক্টের মধ্যে একটি ইন্টারফেস, যা দোভাষীকে অবজেক্ট তৈরি হওয়ার সাথে সাথে এবং থেকে রেফারেন্স ট্র্যাক করতে দেয়।

সি-এক্সটেনশন লিখতে বাধা ব্যবহার না করেই বস্তুর নতুন রেফারেন্স তৈরি করতে পারে, এই ক্ষেত্রে বস্তুগুলিকে ছায়াময় হিসেবে চিহ্নিত করা হয়। অথবা লেখা-বাধা অরক্ষিত . মনে রাখা সেটটি কেবল পুরানো এর একটি তালিকা একটি নতুন এর অন্তত একটি রেফারেন্স সহ বস্তু বস্তু।

রুবি আবর্জনা সংগ্রহ কর্মক্ষমতা কাস্টমাইজ করুন

এখন যেহেতু আপনি বুঝতে পেরেছেন যে রুবি জিসি কীভাবে আপনার অ্যাপ্লিকেশনের মেমরি পরিচালনা করে, এখন সময় এসেছে GC-এর আচরণ কাস্টমাইজ করার জন্য উপলব্ধ বিকল্পগুলি দেখার৷

এখানে এনভায়রনমেন্ট ভেরিয়েবল রয়েছে যা আপনি রুবি জিসি-এর কর্মক্ষমতা নিয়ন্ত্রণ করতে ব্যবহার করতে পারেন এবং ফলস্বরূপ, আপনার অ্যাপ্লিকেশনের কর্মক্ষমতা উন্নত করতে পারেন:

RUBY_GC_HEAP_INIT_SLOTS
RUBY_GC_HEAP_FREE_SLOTS
RUBY_GC_HEAP_GROWTH_FACTOR
RUBY_GC_HEAP_GROWTH_MAX_SLOTS
RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR
and other variables

আসুন এখানে গুরুত্বপূর্ণ পরামিতি সম্পর্কে কথা বলি, একে একে:

  • RUBY_GC_HEAP_INIT_SLOTS :রুবি হিপে স্লটের প্রাথমিক সংখ্যা নির্ধারণ করে এবং ডিফল্টরূপে 10000 এ সেট করা হয়। আপনি এই প্যারামিটারটি পরিবর্তন করতে চাইতে পারেন যদি আপনি নিশ্চিত হন যে আপনার অ্যাপ প্রাথমিকভাবে এর বেশিরভাগ বস্তু বরাদ্দ করবে।
  • RUBY_GC_HEAP_FREE_SLOTS :ন্যূনতম সংখ্যক বিনামূল্যের স্লট নিয়ন্ত্রণ করে যা একটি GC চক্রের ঠিক পরে উপলব্ধ হতে হবে। এর ডিফল্ট মান হল 4096। এই মানটি প্রথম হিপ বৃদ্ধির সময় রানটাইমে শুধুমাত্র একবার ব্যবহার করা হয়।
  • RUBY_GC_HEAP_GROWTH_FACTOR :যে ফ্যাক্টর দ্বারা রুবি ইন্টারপ্রেটারের কাছে উপলভ্য স্তূপ বৃদ্ধি পায়। এর ডিফল্ট মান হল 1.8। এটি পরিবর্তন করা সামান্য অর্থপূর্ণ, কারণ রুবি ইতিমধ্যেই গাদা বৃদ্ধিতে আক্রমণাত্মক। আপনি যদি এটি কমানোর চেষ্টা করেন তবে এটি খুব বেশি পার্থক্য করবে না কারণ আধুনিক দোভাষীগুলিতে চাহিদা অনুযায়ী স্তূপ বরাদ্দ করা হয়।
  • RUBY_GC_HEAP_GROWTH_MAX_SLOTS :সর্বোচ্চ সংখ্যক স্লট রুবি একবারে হিপ স্পেসে যোগ করতে পারে। ডিফল্ট মান হল 0, যা সংখ্যার কোন সীমার জন্য দাঁড়ায়। যদি আপনার অ্যাপকে তার জীবদ্দশায় লক্ষ লক্ষ বস্তু বরাদ্দ করতে হয়, তাহলে আপনি এই প্যারামিটারে একটি ক্যাপ রাখতে চাইতে পারেন। যাইহোক, এটি আপনার অ্যাপের GC সময়ের উপর বেশ কম প্রভাব ফেলবে।
  • RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR দোভাষীকে একটি প্রধান GC চক্র চালাতে বাধ্য করে যখন মেমরিতে পুরানো বস্তুর মোট সংখ্যা =এই সংখ্যার চেয়ে বেশি x শেষ GC চক্রের পরে মেমরিতে পুরানো বস্তুর সংখ্যা। আপনি এই সংখ্যা বাড়াতে চাইতে পারেন যদি আপনি মনে করেন আপনার অনেক বস্তু পুরানো প্রজন্মে প্রবেশ করার পরে অব্যবহৃত হয়ে যাবে। যাইহোক, এটি খুব কমই প্রয়োজন।
  • RUBY_GC_MALLOC_LIMIT নতুন প্রজন্মের জন্য ম্যালোক কলের সর্বনিম্ন সীমা। এর ডিফল্ট মান হল 16 MB। RUBY_GC_MALLOC_LIMIT_MAX একই malloc কলের সর্বোচ্চ সীমা। এর ডিফল্ট মান 32 MB। আপনার অ্যাপ্লিকেশন যদি গড় মেমরির চেয়ে বেশি ব্যবহার করে তবে আপনি এই দুটি সীমা বাড়াতে চাইতে পারেন। তবে খেয়াল রাখবেন এগুলো যেন বেশি না বাড়ায়। অন্যথায়, তারা উচ্চ শিখর মেমরি খরচ হতে পারে. সর্বদা এই সীমাগুলি ক্রমবর্ধমানভাবে বাড়ান — বলুন, 4 বা 8 এমবি।
  • RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR নতুন প্রজন্মের জন্য malloc সীমা বৃদ্ধির ফ্যাক্টর। এর ডিফল্ট মান হল 1.4। আপনার অ্যাপটি একবারে পুরো না হয়ে খণ্ডে মেমরি বরাদ্দ করলে এই সংখ্যা বাড়ানোর কথা বিবেচনা করা উচিত।
  • একইভাবে, RUBY_GC_OLDMALLOC_LIMIT এবং RUBY_GC_OLDMALLOC_LIMIT_MAX পুরানো প্রজন্মের জন্য সর্বনিম্ন এবং সর্বোচ্চ malloc সীমা। এই প্যারামিটারের ডিফল্ট মান হল 16 MB এবং 128 MB৷
  • RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR এই সীমা বৃদ্ধি ফ্যাক্টর হয়. এর ডিফল্ট মান হল 1.2। আপনি সর্বাধিক প্রভাবের জন্য নতুন প্রজন্মের সীমার সাথে এগুলি পরিবর্তন করার কথা বিবেচনা করতে পারেন।

রুবিতে ফাইন-টিউনিং আবর্জনা সংগ্রহ

আমরা আপনার অ্যাপ্লিকেশনের সামগ্রিক কর্মক্ষমতা উন্নত করতে সাহায্য করার জন্য GC মডিউল কাস্টমাইজ করার কিছু সাধারণ এবং সহজ উপায় নিয়ে আলোচনা করেছি। যাইহোক, এই tweaks সব ক্ষেত্রে কাজ নাও হতে পারে. কি কাস্টমাইজ করতে হবে তা সিদ্ধান্ত নেওয়ার আগে আপনাকে আপনার অ্যাপের মেমরি ব্যবহারের প্যাটার্ন বের করতে হবে।

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

আপনার অ্যাপ্লিকেশান অদ্ভুতভাবে আচরণ করলে অবশ্যই GC প্যারামিটারগুলি দেখুন। এখানে একটি ছোট পরিবর্তন আপনার অ্যাপের মেমরি খরচ কমিয়ে আনতে এবং মেমরি ব্লাট প্রতিরোধ করতে অনেক দূর এগিয়ে যেতে পারে।

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

মজা করুন কোডিং!


  1. রুবি 2.6-এ 9টি নতুন বৈশিষ্ট্য

  2. রুবি 2.5-এ কর্মক্ষমতার উন্নতি

  3. রুবিতে ব্যবহারিক লিঙ্কড তালিকা

  4. রুবিতে ব্যবহারিক গ্রাফ তত্ত্ব