आपके कोड के प्रदर्शन को मापने में मदद करने के लिए रूबी की मानक लाइब्रेरी में एक बेंचमार्किंग टूल है। यह पता लगाने के लिए कि कौन सा सबसे तेज़ है, दो कार्यान्वयनों की तुलना करते समय यह सबसे उपयोगी है।
इस उदाहरण में, हमें हैश को स्ट्रिंग कुंजियों (जैसे {"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
. का उपयोग करते हैं हमारे नए सरणी को वापस हैश में बदलने के लिए।
बेंचमार्क.माप
अब जबकि हमारे पास एक कार्यशील कार्यान्वयन है, हम रूबी के बेंचमार्क मॉड्यूल का उपयोग यह देखने के लिए कर सकते हैं कि यह कैसा प्रदर्शन करता है।
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 समय दोनों को जोड़ा गया, और वास्तविक समय (या दीवार घड़ी का समय) जो ब्लॉक को ब्रैकेट में निष्पादित करने में लगा।
दीवार का समय हमें दिखाता है कि हम 800 मिलीसेकंड से थोड़ा अधिक समय में 50,000 से अधिक बार कोड के ब्लॉक को चला सकते हैं। जबकि यह एक प्रभावशाली संख्या है, हम इसका अर्थ तब तक नहीं जानते जब तक हम इसकी तुलना कोड के किसी अन्य कार्यान्वयन से नहीं करते।
बेंचमार्क.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 पर बताएं।