আপনি কি জানতেন যে একটি রানিং প্রসেসের সব মেথড কল লগ করা সম্ভব রিয়েল-টাইমে? অথবা একটি রানিং প্রসেসের ভেতরে কোড ইনজেক্ট করে এক্সিকিউট করা সম্ভব? আপনি পারেন—rbtrace জেমের জাদুতে।
rbtrace জেমের দুটি অংশ আছে। প্রথমটি একটি লাইব্রেরি যা আপনি যে কোড ট্রেস করতে চান সেটিতে ইনক্লুড করতে হয়। দ্বিতীয়টি একটি কমান্ডলাইন ইউটিলিটি ট্রেস ডেটা কোয়েরি করার জন্য।
একটি সহজ উদাহরণ দেখি। যে কোডটি আমরা ট্রেস করবো সেটি খুব সহজ। শুধু rbtrace জেম রিকোয়ার্ড করতে হবে।
require 'rbtrace'
require 'digest'
require 'securerandom'
# একটি ইনফিনিট লুপ
while true
# কিছু কাজ করুন
Digest::SHA256.digest SecureRandom.random_bytes(2**8)
# প্রতিটি ইটারেশনে এক সেকেন্ড স্লিপ
sleep 1
end
এখন এই প্রোগ্রামটি রান করি:
$ ruby trace.rb &
[1] 12345
এই প্রসেস ID কে rbtrace কমান্ডলাইন টুলে দিই। -f অপশন "ফায়ারহোজ" মোড বোঝায়, যা সব কিছু স্ক্রিনে প্রিন্ট করে।
$ rbtrace -p 12345 -f
*** attached to process 12345
Fixnum#** <0.000010>
SecureRandom.random_bytes
Integer#to_int <0.000005>
SecureRandom.gen_random
OpenSSL::Random.random_bytes <0.002223>
SecureRandom.gen_random <0.002243>
SecureRandom.random_bytes <0.002290>
Digest::SHA256.digest
Digest::Class#initialize <0.000004>
Digest::Instance#digest
Digest::Base#reset <0.000005>
Digest::Base#update <0.000210>
Digest::Base#finish <0.000006>
Digest::Base#reset <0.000005>
Digest::Instance#digest <0.000267>
Digest::SHA256.digest <0.000308>
Kernel#rand
Kernel#respond_to_missing? <0.000008>
Kernel#rand <0.000071>
Kernel#sleep <1.003233>
এটি খুব চমৎকার! আমরা প্রতিটি মেথড কল এবং সেটিতে ব্যয় হওয়া সময় দেখতে পাচ্ছি।
যদি আমরা কোনো নির্দিষ্ট মেথডে ফোকাস করতে চাই, তবে -m অপশন ব্যবহার করতে পারি।
$ rbtrace -p 12345 -m digest
*** attached to process 12345
Digest::SHA256.digest
Digest::Instance#digest <0.000201>
Digest::SHA256.digest <0.000220>
Digest::SHA256.digest
Digest::Instance#digest <0.000287>
Digest::SHA256.digest <0.000343>
এই জেমের সম্ভবত সবচেয়ে কুল ব্যবহার হচ্ছে একটি রানিং ওয়েব সার্ভার থেকে হিপ ডাম্প পাওয়া। হিপ ডাম্পে মেমরির প্রতিটি অবজেক্ট এবং মেটাডেটা থাকে এবং প্রোডাকশনে মেমরি লিক ডিবাগ করার জন্য খুব উপকারী।
হিপ ডাম্প পেতে নিচের কমান্ডটি ব্যবহার করুন, Sam Saffron-এর এই পোস্ট থেকে নেওয়া।
$ bundle exec rbtrace -p <SERVER PID HERE> -e 'Thread.new{GC.start;require "objspace";io=File.open("/tmp/ruby-heap.dump", "w"); ObjectSpace.dump_all(output: io); io.close}'
সতর্ক থাকুন, হিপ ডাম্প খুব বড় হতে পারে—রেইলস প্রসেসের জন্য কয়েক শত মেগাবাইট পর্যন্ত। একদম ছোট একটি স্যাম্পল:
[
{
"type": "ROOT",
"root": "vm",
"references": [
"0x7fb7d38bc3f0", "0x7fb7d38b79b8", "0x7fb7d38dff80", "0x7fb7d38bff50",
"0x7fb7d38bff00", "0x7fb7d38b4bf0", "0x7fb7d38bfe88", "0x7fb7d38bfe60",
"0x7fb7d38ddc80", "0x7fb7d38dffa8", "0x7fb7d382fbd0", "0x7fb7d382fbf8"
]
},
{
"type": "ROOT",
"root": "machine_context",
"references": [
"0x7fb7d382fbf8", "0x7fb7d382fbf8", "0x7fb7d3827d40", "0x7fb7d3827a70",
"0x7fb7d38becb8", "0x7fb7d38bed08", "0x7fb7d38ddc80", "0x7fb7d3827e58",
"0x7fb7d3827e58", "0x7fb7d38becb8", "0x7fb7d38becb8", "0x7fb7d38bc328",
"0x7fb7d38bc378", "0x7fb7d38ddc80", "0x7fb7d3835008", "0x7fb7d3835008",
"0x7fb7d3835008", "0x7fb7d3835008", "0x7fb7d3835008"
]
}
... আরও এন্ট্রি
]