सामान्य तौर पर, एक संरचना की तुलना में OpenStruct का उपयोग करने के फायदे और नुकसान क्या हैं? किस प्रकार के सामान्य उपयोग-मामले इनमें से प्रत्येक में फिट होंगे?
सामान्य तौर पर, एक संरचना की तुलना में OpenStruct का उपयोग करने के फायदे और नुकसान क्या हैं? किस प्रकार के सामान्य उपयोग-मामले इनमें से प्रत्येक में फिट होंगे?
जवाबों:
A के साथ OpenStruct
, आप मनमाने ढंग से विशेषताएँ बना सकते हैं। एक Struct
, दूसरे हाथ पर, जब आप इसे बनाने के उसके गुण परिभाषित होने चाहिए। एक के ऊपर एक का चुनाव मुख्य रूप से इस बात पर आधारित होना चाहिए कि क्या आपको बाद में विशेषताओं को जोड़ने में सक्षम होना चाहिए।
उनके बारे में सोचने का तरीका एक तरफ हैश के बीच स्पेक्ट्रम का मध्य मैदान है और दूसरी तरफ कक्षाएं। वे डेटा के बीच एक अधिक ठोस संबंध की तुलना में एक करते हैं Hash
, लेकिन उनके पास एक वर्ग के रूप में उदाहरण के तरीके नहीं हैं। एक समारोह के लिए विकल्पों का एक गुच्छा, उदाहरण के लिए, हैश में समझदारी; वे केवल शिथिल संबंधित हैं। किसी फ़ंक्शन द्वारा आवश्यक नाम, ईमेल और फ़ोन नंबर को एक साथ Struct
या में पैक किया जा सकता है OpenStruct
। यदि उस नाम, ईमेल और फोन नंबर को "प्रथम अंतिम" और "अंतिम, पहला" दोनों स्वरूपों में नाम प्रदान करने के लिए तरीकों की आवश्यकता है, तो आपको इसे संभालने के लिए एक वर्ग बनाना चाहिए।
class Point < Struct.new(:x, :y); methods here; end
Point = Struct.new(:x, :y) { methods here }
। ( स्रोत ) बेशक, { ... }
वहाँ एक मल्टी-लाइन ब्लॉक ( do ... end
) के रूप में लिखा जा सकता है और मुझे लगता है, यह पसंदीदा तरीका है।
अन्य बेंचमार्क:
require 'benchmark'
require 'ostruct'
REP = 100000
User = Struct.new(:name, :age)
USER = "User".freeze
AGE = 21
HASH = {:name => USER, :age => AGE}.freeze
Benchmark.bm 20 do |x|
x.report 'OpenStruct slow' do
REP.times do |index|
OpenStruct.new(:name => "User", :age => 21)
end
end
x.report 'OpenStruct fast' do
REP.times do |index|
OpenStruct.new(HASH)
end
end
x.report 'Struct slow' do
REP.times do |index|
User.new("User", 21)
end
end
x.report 'Struct fast' do
REP.times do |index|
User.new(USER, AGE)
end
end
end
अधीर के लिए जो बेंचमार्क परिणामों का विचार प्राप्त करना चाहते हैं, उन्हें स्वयं चलाने के बिना, यहां ऊपर दिए गए कोड का आउटपुट है (एक एमबी प्रो 2.4GHz i7 पर)
user system total real
OpenStruct slow 4.430000 0.250000 4.680000 ( 4.683851)
OpenStruct fast 4.380000 0.270000 4.650000 ( 4.649809)
Struct slow 0.090000 0.000000 0.090000 ( 0.094136)
Struct fast 0.080000 0.000000 0.080000 ( 0.078940)
अपडेट करें:
रूबी के रूप में 2.4.1 OpenStruct और संरचना गति में बहुत करीब हैं। Https://stackoverflow.com/a/43987844/128421 देखें
पहले:
पूर्णता के लिए: संरचना बनाम कक्षा बनाम हैश बनाम ओपनस्ट्रीम
रूबी 1.9.2, (1 के 4 कोर x86_64, 8 जीबी रैम में से 1) पर इसी तरह के कोड को चलाना [स्तंभ संरेखित करने के लिए संपादित तालिका]:
1 Mio संरचनाएं बनाना: 1.43 सेकंड, 219 MB / 90MB (गुण / रेस) 1 Mio क्लास इंस्टेंसेस बनाना: 1.43 सेकंड, 219 MB / 90MB (पुण्य / रेस) 1 Mio हैशिंग बनाना: 4.46 सेकंड, 493 MB / 364MB (पुण्य / रेस) 1 Mio OpenStructs बनाना: 415.13 सेकंड, 2464 MB / 2.3GB (गुण / रेस) # Hashes की तुलना में 100x धीमा 100K OpenStructs बनाना: 10.96 सेकंड, 369 MB / 242MB (गुण / रेस)
OpenStructs हैं sloooooow और स्मृति गहन , और बड़े डेटा सेट के लिए अच्छी तरह से बड़े पैमाने नहीं है
1 Mio OpenStructs बनाना ~ Mio Hashes बनाने की तुलना में ~ 100x धीमा है ।
start = Time.now
collection = (1..10**6).collect do |i|
{:name => "User" , :age => 21}
end; 1
stop = Time.now
puts "#{stop - start} seconds elapsed"
दोनों के लिए उपयोग के मामले काफी भिन्न हैं।
आप रूबी 1.9 में संरचना वर्ग को struct
सी में घोषणा के बराबर मान सकते हैं । रूबी Struct.new
में तर्कों के रूप में फ़ील्ड नामों का एक सेट लेता है और एक नया वर्ग देता है। इसी तरह, सी में, एक struct
घोषणापत्र खेतों का एक सेट लेता है और प्रोग्रामर को नए जटिल प्रकार का उपयोग करने की अनुमति देता है जैसे वह किसी भी प्रकार का निर्माण करता है।
माणिक:
Newtype = Struct.new(:data1, :data2)
n = Newtype.new
सी:
typedef struct {
int data1;
char data2;
} newtype;
newtype n;
OpenStruct वर्ग की तुलना सी में अनाम संरचना घोषणा से की जा सकती है। यह प्रोग्रामर को एक जटिल प्रकार का उदाहरण बनाने की अनुमति देता है ।
माणिक:
o = OpenStruct.new(data1: 0, data2: 0)
o.data1 = 1
o.data2 = 2
सी:
struct {
int data1;
char data2;
} o;
o.data1 = 1;
o.data2 = 2;
यहाँ कुछ सामान्य उपयोग के मामले हैं।
OpenStructs का उपयोग आसानी से हैश को एक-ऑफ ऑब्जेक्ट में बदलने के लिए किया जा सकता है जो सभी हैश कीज़ का जवाब देता है।
h = { a: 1, b: 2 }
o = OpenStruct.new(h)
o.a = 1
o.b = 2
शॉर्टहैंड क्लास परिभाषाओं के लिए संरचनाएं उपयोगी हो सकती हैं।
class MyClass < Struct.new(:a,:b,:c)
end
m = MyClass.new
m.a = 1
OpenStructs काफी अधिक मेमोरी का उपयोग करते हैं और स्ट्रक्चर बनाम स्लो परफॉर्मर होते हैं।
require 'ostruct'
collection = (1..100000).collect do |index|
OpenStruct.new(:name => "User", :age => 21)
end
मेरे सिस्टम पर निम्नलिखित कोड 14 सेकंड में निष्पादित किया गया और 1.5 जीबी मेमोरी का उपभोग किया गया। आपका माइलेज भिन्न हो सकता है:
User = Struct.new(:name, :age)
collection = (1..100000).collect do |index|
User.new("User",21)
end
यह लगभग तुरंत समाप्त हो गया और 26.6 एमबी मेमोरी का उपभोग किया।
Struct
:
>> s = Struct.new(:a, :b).new(1, 2)
=> #<struct a=1, b=2>
>> s.a
=> 1
>> s.b
=> 2
>> s.c
NoMethodError: undefined method `c` for #<struct a=1, b=2>
OpenStruct
:
>> require 'ostruct'
=> true
>> os = OpenStruct.new(a: 1, b: 2)
=> #<OpenStruct a=1, b=2>
>> os.a
=> 1
>> os.b
=> 2
>> os.c
=> nil
नई विधि के संबंध में एपीआई पर एक नजर है। बहुत सारे अंतर वहां पाए जा सकते हैं।
व्यक्तिगत रूप से, मैं काफी OpenStruct पसंद करता हूं, क्योंकि मुझे ऑब्जेक्ट की संरचना को पहले से परिभाषित नहीं करना है, और जैसा मैं चाहता हूं, वैसे ही सामान जोड़ें। मुझे लगता है कि इसका मुख्य (डिस) लाभ होगा?
@Robert कोड का उपयोग करके, मैं Hashie :: मैश को बेंचमार्क आइटम में जोड़ता हूं और यह परिणाम मिला है:
user system total real
Hashie::Mash slow 3.600000 0.000000 3.600000 ( 3.755142)
Hashie::Mash fast 3.000000 0.000000 3.000000 ( 3.318067)
OpenStruct slow 11.200000 0.010000 11.210000 ( 12.095004)
OpenStruct fast 10.900000 0.000000 10.900000 ( 12.669553)
Struct slow 0.370000 0.000000 0.370000 ( 0.470550)
Struct fast 0.140000 0.000000 0.140000 ( 0.145161)
वास्तव में सवाल का जवाब नहीं है, लेकिन एक बहुत महत्वपूर्ण विचार है अगर आप प्रदर्शन के बारे में परवाह करते हैं । कृपया ध्यान दें कि हर बार जब आप OpenStruct
ऑपरेशन करते हैं, तो विधि कैश को साफ़ करता है, जिसका अर्थ है कि आपका आवेदन धीमा प्रदर्शन करेगा। धीमेपन या नहीं के OpenStruct
बारे में सिर्फ यह नहीं है कि यह अपने आप से कैसे काम करता है, बल्कि इसका अर्थ है कि उनका उपयोग पूरे आवेदन को लाता है: https://github.com/charliesome/charlie.bz/blob/master/posts/things-that -clear-rubys-method-cache.md # openstructs