रूबी की मानक लाइब्रेरी में आपके कोड के प्रदर्शन को मापने में मदद के लिए एक बेंचमार्किंग टूल है। यह दो कार्यान्वयन की तुलना करते समय सबसे उपयोगी होता है, यह पता लगाने के लिए कि कौन सा सबसे तेज़ है।
इस उदाहरण में, हमें स्ट्रिंग कुंजी वाले हैश (जैसे {"foo" => "bar"}) को सिम्बल वाले हैश (जैसे {:foo => "bar"}) में बदलने का काम सौंपा गया है। उदाहरणों के दौरान, हम अंग्रेजी वर्णमाला के प्रत्येक अक्षर के लिए एक कुंजी और एक मान के साथ एक हैश का उपयोग करेंगे।
इस हैश को टाइप किए बिना जल्दी से जनरेट करने के लिए, हम अक्षरों की एक रेंज को अपने टेस्टिंग हैश में बदल देंगे। हम इसे बाद में उपयोग करने के लिए input वेरिएबल में रखेंगे।
input = ("a".."z").map {|letter| [letter, letter]}.to_h # => {"a"=>"a", "b"=>"b", "c"=>"c", "d"=>"d", "e"=>"e", "f"=>"f", "g"=>"g", "h"=>"h", "i"=>"i", "j"=>"j", "k"=>"k", "l"=>"l", "m"=>"m", "n"=>"n", "o"=>"o", "p"=>"p", "q"=>"q", "r"=>"r", "s"=>"s", "t"=>"t", "u"=>"u", "v"=>"v", "w"=>"w", "x"=>"x", "y"=>"y", "z"=>"z"}
अब जब हमारे पास अपने कार्यान्वयन का परीक्षण करने के लिए input वेरिएबल है, तो हम एक लिखेंगे कि यह कैसा प्रदर्शन करता है। हमारे इनपुट हैश में सभी कुंजियों को स्ट्रिंग के बजाय सिम्बल में बदलने के लिए एक अच्छा वन-लाइनर इस तरह दिखता है:
input.map { |key, value| [key.to_sym, value] }.to_h # => {:a=>"a", :b=>"b", :c=>"c", :d=>"d", :e=>"e", :f=>"f", :g=>"g", :h=>"h", :i=>"i", :j=>"j", :k=>"k", :l=>"l", :m=>"m", :n=>"n", :o=>"o", :p=>"p", :q=>"q", :r=>"r", :s=>"s", :t=>"t", :u=>"u", :v=>"v", :w=>"w", :x=>"x", :y=>"y", :z=>"z"}
यह कार्यान्वयन हैश पर लूप करने के लिए map मेथड का उपयोग करता है ताकि प्रत्येक कुंजी-मान जोड़ी के लिए एक ब्लॉक चलाया जा सके। ब्लॉक में, यह कुंजी को सिम्बल में बदलता है और नए बनाए गए सिम्बल कुंजी और अनछुए मान के साथ दो-तत्व सरणी लौटाता है।
map कमांड का परिणाम 26 कुंजी-मान सरणियों के साथ एक सरणी है। चूंकि हमें एक हैश चाहिए, हम अपने नए सरणी को वापस हैश में बदलने के लिए #to_h का उपयोग करते हैं।
Benchmark.measure
अब जब हमारे पास एक कार्यशील कार्यान्वयन है, तो हम रूबी के Benchmark मॉड्यूल का उपयोग करके देख सकते हैं कि यह कैसा प्रदर्शन करता है।
require 'benchmark'
input = ('a'..'z').map { |letter| [letter, letter] }.to_h
puts Benchmark.measure { 50_000.times do
input.map { |key, value| [key.to_sym, value] }.to_h
end }
Benchmark.measure एक ब्लॉक लेता है, जिसे निष्पादित करते समय यह ट्रैक करता है कि इसे निष्पादित होने में कितना समय लगा। यह एक रिपोर्ट स्ट्रिंग लौटाता है, जिसे puts का उपयोग करके कंसोल पर प्रिंट किया जाता है।
चूंकि यह कोड का एक त्वरित टुकड़ा है, हम इसे 50,000 बार चलाते हैं ताकि हमें कुछ दृश्यमान परिणाम मिलें।
$ ruby bench.rb
0.810000 0.000000 0.810000 ( 0.816964)
रिपोर्ट स्ट्रिंग चार संख्याएं दिखाती है, जो यूजर CPU समय (आपके कोड को निष्पादित करने में लगा समय), सिस्टम CPU समय (कर्नेल में लगा समय), दोनों यूजर और सिस्टम CPU समय को जोड़ा गया, और वास्तविक समय (या वॉल क्लॉक समय) जो ब्लॉक को निष्पादित करने में लगा कोष्ठक में दर्शाता है।
वॉल समय हमें दिखाता है कि हम ऊपर दिए गए कोड ब्लॉक को 50,000 बार 800 मिलीसेकंड से थोड़ा अधिक में चला सकते हैं। हालांकि यह एक प्रभावशाली संख्या है, हम नहीं जानते कि इसका क्या अर्थ है जब तक हम इसकी तुलना कोड के किसी अन्य कार्यान्वयन से नहीं करते।
Benchmark.bm
Benchmark.measure के अलावा, रूबी Benchmark.bm प्रदान करता है, जो कई कोड नमूने चला सकता है और उनके परिणाम प्रिंट कर सकता है। प्रत्येक नमूने के लिए, हम एक नाम के साथ Benchmark#report को कॉल करेंगे, और निष्पादित किए जाने वाले ब्लॉक को।
require 'benchmark'
input = ("a".."z").map { |letter| [letter, letter] }.to_h
n = 50_000
Benchmark.bm do |benchmark|
benchmark.report("Hash[]") do
n.times do
input.map { |key, value| [key.to_sym, value] }.to_h
end
end
benchmark.report("{}.tap") do
n.times do
{}.tap do |new_hash|
input.each do |key, value|
new_hash[key.to_sym] = value
end
end
end
end
end
इस बेंचमार्क में, हम दो कार्यान्वयन का परीक्षण करने के लिए Benchmark.bm का उपयोग करेंगे, प्रत्येक को 50,000 बार चलाकर। पहला माप ब्लॉक पहले के उदाहरण के समान है।
दूसरे माप ब्लॉक में, हम एक लंबे कार्यान्वयन का उपयोग करते हैं, जो पहले एक नया हैश बनाता है। यह स्ट्रिंग-कुंजी हैश पर लूप करता है, और प्रत्येक आइटम के लिए नए हैश में एक तत्व जोड़ता है। इस तरह, जब यह समाप्त होता है तो इसे हैश को सरणी में बदलने की आवश्यकता नहीं होती, और वापस हैश में।
बेंचमार्क को फिर से चलाने से पता चलेगा कि यह कार्यान्वयन 25% से अधिक तेज़ है, हालांकि कोड पहले आजमाए गए वन-लाइनर की तुलना में लंबा (और थोड़ा कम चतुर) है।
$ ruby bench.rb
user system total real
Hash[] 0.850000 0.000000 0.850000 ( 0.851106)
{}.tap 0.610000 0.020000 0.630000 ( 0.637070)
अधिक बेंचमार्किंग
अपने कोडबेस में कोड के एक महत्वपूर्ण टुकड़े पर काम करते समय, विभिन्न कार्यान्वयनों की तुलना करने के लिए बेंचमार्क चलाने से उनके निष्पादन गति में अधिक अंतर्दृष्टि मिल सकती है। विभिन्न कार्यान्वयनों की तुलना करके यह समझने के लिए कि वे प्रदर्शन को कैसे प्रभावित करते हैं, आप एंटी-पैटर्न से बचने और तेज़ रूबी लिखने में सक्षम होंगे।
टिप: बहुत सारे सामान्य मुहावरे पूर्व-बेंचमार्क्ड हैं, और उनके परिणाम फास्ट-रूबी के रूप में प्रकाशित होते हैं। उदाहरणों को पढ़ने से आपको भविष्य में कुछ बेंचमार्किंग बच सकती है।
इस उदाहरण के लिए और भी विकल्प हैं जिन्हें आप परख सकते हैं, और रूबी की बेंचमार्किंग लाइब्रेरी में बहुत अधिक परिष्कृत विशेषताएं हैं जिन्हें आप आज़मा सकते हैं, लेकिन यह रूबी में बेंचमार्किंग कैसे काम करती है, इसका एक अच्छा परिचय देता है। यदि आप बेंचमार्किंग के बारे में अधिक जानना चाहते हैं, या आपके कोई प्रश्न या सुझाव हैं, तो कृपया @AppSignal पर हमें बताएं।