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

ObjectSpace বোঝা: আপনার রুবি অ্যাপ্লিকেশনের রানটাইম স্টেট পরিদর্শন

যদি আপনি জানতে চান আপনার রুবি অ্যাপ্লিকেশনের সাথে কী ঘটছে…

এখানে কোনো ফ্যান্সি GUI টুল নেই…

তবে আমাদের কাছে ObjectSpace মডিউল আছে!

ObjectSpace আপনাকে আপনার অ্যাপ্লিকেশনের বর্তমান অবস্থা সম্পর্কে তথ্য দেয়।

আসুন আবিষ্কার করি এটি কীভাবে কাজ করে।

অবজেক্ট গণনা

ObjectSpace ব্যবহার করে আপনি জানতে পারেন আপনার প্রোগ্রামে বর্তমানে কোন অবজেক্টগুলো 'জীবিত'।

একটি অবজেক্টের জীবিত থাকতে কী অর্থ?

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

যদি একটি অবজেক্টে পৌঁছানো সম্ভব না হয় তবে এর অর্থ সেটি মেমরি থেকে সরানো নিরাপদ।

উদাহরণ:

# 'name' ভেরিয়েবলটি 'Dave' স্ট্রিংটির রেফারেন্স ধারণ করে
name = 'Dave'
# 'name' ভেরিয়েবলটি এখন 'John'-কে নির্দেশ করছে
# 'Dave'-এর দিকে আর কোনো রেফারেন্স নেই
name = 'John'

এখন ObjectSpace-এর একটি উদাহরণ দেখি:

require 'objspace'
# এটি বৈধ রুবি সিনট্যাক্স, কিন্তু irb/pry-তে কাজ করে না
ObjectSpace
  .each_object
  .inject(Hash.new 0) { |h,o| h[o.class] += 1; h }
  .sort_by { |k,v| -v }
  .take(10)
  .each { |klass, count| puts "#{count.to_s.ljust(10)} #{klass}" }

# কপি-পেস্ট ভার্সন (irb/pry-তে ব্যবহারের জন্য)
ObjectSpace.each_object.inject(Hash.new 0) { |h,o| h[o.class] += 1; h }.sort_by { |k,v| -v }.take(10).each { |klass, count| puts "#{count.to_s.ljust(10)} #{klass}" }

এটি আপনার টপ-১০ ক্লাসের অবজেক্ট কাউন্ট সহ একটি টেবিল প্রিন্ট করবে।

Count Class
-------------------------
5436 String
315 Class
251 Array
101 Encoding
69 Regexp
45 Hash
26 Module
25 Gem::Version
22 Gem::StubSpecification::StubLine
22 Gem::StubSpecification

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

অবজেক্টের সাথে মজা

ObjectSpace ব্যবহার করলে আপনি শুধু অবজেক্ট সম্পর্কে তথ্য না, বরং সত্যিকারের অবজেক্টগুলোর অ্যাক্সেস পান, তাই আপনি কিছু মজার জিনিস করতে পারেন যেমন সকল স্ট্রিংয়ের ভ্যালু প্রিন্ট করা বা সকল File অবজেক্টের পাথ প্রিন্ট করা।

উদাহরণ:

ObjectSpace
  .each_object(String)
  .sort_by { |s| s.size }
  .each { |s| p s }

এটি মেমরিতে থাকা সকল স্ট্রিং আকার অনুযায়ী সর্ট করে প্রিন্ট করবে। আপনি লক্ষ্য করবেন যে অনেক স্ট্রিং আছে যা আপনি তৈরি করেননি, সেগুলো রুবি ইন্টারপ্রেটার তৈরি করেছে।

ব্যবহারিক কাজ?

বহুত বড় একটি না, এটি মুখ্যতঃ ডিবাগিং এবং আপনার অ্যাপ সম্পর্কে স্ট্যাট্স জुटানোর জন্য 🙂

অবজেক্ট মেমরি আকার

আপনি আর একটা জিনিস করতে পারেন ObjectSpace.memsize_of ব্যবহার করে একটি নির্দিষ্ট অবজেক্টের মেমরি আকার জানতে।

উদাহরণ:

o = "a" * 100
ObjectSpace.memsize_of(o)

একটি জিনিস মনে রাখবেন ডকুমেন্টেশন থেকে এই সতর্কতা:

"নোট করুন যে রিটার্ন করা আকার অসম্পূর্ণ। আপনাকে এই তথ্যকে কেবল একটি HINT হিসেবে বিবেচনা করতে হবে।"

যদি আপনি এই মেথডটি বিভিন্ন ধরণের অবজেক্টের সাথে চেষ্টা করেন আপনি কিছু মজার জিনিস খুঁজে পাবেন, যেমন Fixnum গুলো সবসময় ০ রিটার্ন করে।

ObjectSpace.memsize_of(42) # 0

কারণটি হল রুবি অভ্যন্তরীণভাবে Fixnum অবজেক্ট তৈরি করে না, আপনি রুবিতে সংখ্যা সম্পর্কে আমার লিখা পোস্ট থেকে এর সম্পর্কে আরও জানতে পারেন।

আর একটি মজার জিনিস হল স্ট্রিং:

ObjectSpace.memsize_of("A" * 22) # 40
ObjectSpace.memsize_of("A" * 23) # 40
ObjectSpace.memsize_of("A" * 24) # 65

আমি "A" * size ব্যবহার করি বড় স্ট্রিং তৈরি করার জন্য টাইপ না করে 🙂

রকুন! এখন কী হলো?

বоловা যায়, রুবিতে ২৪ ক্যারেক্টার ছোট স্ট্রিং-এর জন্য একটি বিল্ট-ইন অপ্টিমাইজেশন আছে, তাই সেটির পর মেমরি ব্যবহারে হঠাৎ বৃদ্ধি হয়। আপনি Pat Shaughnessy-এর এই পোস্টে এর বিস্তারিত দেখতে পারেন।

এলিয়াসড মেথড খুঁজে বের করার উপায়

রুবিতে সকল এলিয়াসড মেথডের একটি 'মাস্টার' তালিকা থাকলে কত ভালো হতো?

কামনা পূরণ!

এটি দেখুন:

class Module
  def aliased_methods
    instance_methods(false)
      .group_by { |m| instance_method(m) }
      .map(&:last)
      .keep_if { |symbols| symbols.length > 1 }
  end
end

এই কোডটি আমি একটি Stackoverflow উত্তর থেকে পেয়েছি। এটি Module ক্লাসে একটি aliased_methods মেথড সংজ্ঞায়িত করে, যা instance_methods মেথড ব্যবহার করে একটি ক্লাসে সংজ্ঞায়িত সকল ইনস্ট্যান্স মেথডের তালিকা পায়।

এটি কিছুটা বিভ্রান্তিকর লাগতে পারে, কিন্তু এটিই মেটাপ্রোগ্রামিং!

এখানে বাকি কোডটি, যা কমপক্ষে একটি 'জীবিত' অবজেক্ট রেখে সব ক্লাসের নামের একটি অ্যারে তৈরি করে, তারপর প্রতিটি ক্লাসে aliased_methods কল করে এবং আউটপুট প্রিন্ট করে।

objects = ObjectSpace.each_object.map(&:class).uniq
objects.each do |klass|
  methods = "\n#{klass}\n#{'-'*20}\n"
  klass.send(:aliased_methods).each do |m1, m2|
    methods << "#{m1.to_s.ljust(15)} #{m2}\n"
  end
  puts methods
end

আউটপুটটি এরকম দেখাবে:

Array
--------------------
inspect  to_s
[]       slice
length   size
find_index index
collect  map
collect! map!

উপসংহার

আশা করি ObjectSpace-এর সাথে করা যাবে এমন কুল জিনিসগুলো শিখে আপনি উপভোগ করেছেন, এখন জামান দিন এবং জানান আপনি কী মজার জিনিস খুঁজে পেলেন!

এই পোস্টটি আপনার সব প্রোগ্রামার বন্ধুদের সাথে শেয়ার করা ভুলবেন না, এটি তাদের কিছু নতুন শিখতে সাহায্য করবে এবং আমাকে আরও পাঠক পাওয়াতে সাহায্য করবে 🙂

  1. রুবি ম্যাট্রিক্স বুঝতে: ডেফিনিশন, অ্যাপ্লিকেশন এবং কীভাবে তৈরি করবেন

  2. রুবি ২.৬-এ MJIT বুঝতে: কীভাবে জাস্ট-ইন-টাইম কম্পাইলার পারফরম্যান্স বাড়ায়

  3. Ruby on Rails মাস্টারিং: এই প্রমাণিত ফ্রেমওয়ার্ক দিয়ে দ্রুত পাওয়ারফুল ওয়েব অ্যাপ বানান

  4. উইন্ডোজ লগঅন অ্যাপ্লিকেশন (winlogon.exe) কী এবং এটি কেন গুরুত্বপূর্ণ