আমি কখন স্ট্রাক্ট বনাম ওপেনস্ট্রাক্ট ব্যবহার করব?


184

সাধারণভাবে, কোনও স্ট্রাক্টের তুলনায় ওপেনস্ট্রাক্ট ব্যবহারের সুবিধা এবং অসুবিধাগুলি কী কী? এগুলির প্রতিটি কী ধরণের সাধারণ ব্যবহারের সাথে খাপ খায়?


1
স্ট্রাক্ট বনাম ওপেনস্ট্রাক্ট বনাম হ্যাশ সম্পর্কে আমার সাম্প্রতিক ব্লগ মন্তব্যে " স্ট্রাক্টস ইনস্ট আউট আউট" সম্পর্কে কিছু মন্তব্য রয়েছে , যদি কেউ আগ্রহী হয় তবেই।
রবার্ট ক্লেমে

হ্যাশ, স্ট্রাক্ট এবং ওপেনস্ট্রাক্টের গতি সম্পর্কিত তথ্য পুরানো। আরও সাম্প্রতিক একটি বেঞ্চমার্কের জন্য stackoverflow.com/a/43987844/128421 দেখুন ।
টিন ম্যান

উত্তর:


172

একটি দিয়ে OpenStruct, আপনি নির্বিচারে বৈশিষ্ট্য তৈরি করতে পারেন। একটি Structঅন্যদিকে, যখন আপনি এটি তৈরি তার গুণাবলী সংজ্ঞায়িত থাকতে হবে। একজনের অপরটির পছন্দ মূলত ভিত্তিক হওয়া উচিত আপনার পরবর্তীকালে গুণাবলী যুক্ত করতে সক্ষম হওয়া দরকার কিনা।

এগুলি সম্পর্কে চিন্তাভাবনা করার উপায়টি হ্যাশগুলির একদিকে এবং অন্যদিকে শ্রেণীর মধ্যবর্তী বর্ণালীটির মাঝের ক্ষেত্র হিসাবে। তারা ডেটার মধ্যে একটি তুলনায় আরও দৃ concrete় সম্পর্ক বোঝায় Hash, তবে তাদের ক্লাসের মতো উদাহরণ পদ্ধতি নেই। একটি ফাংশনের জন্য বিকল্পগুলির একটি গোছা, উদাহরণস্বরূপ, একটি হ্যাশটি বোঝায়; তারা কেবল আলগাভাবে সম্পর্কিত। একটি ক্রিয়াকলাপের জন্য প্রয়োজনীয় একটি নাম, ইমেল এবং ফোন নম্বর একটি Structবা একসাথে প্যাকেজ করা যেতে পারে OpenStruct। যদি সেই নাম, ইমেল এবং ফোন নম্বরটির জন্য "প্রথম সর্বশেষ" এবং "শেষ, প্রথম" উভয় ফর্ম্যাটে নাম সরবরাহ করতে প্রয়োজন হয়, তবে আপনার এটি পরিচালনা করার জন্য একটি শ্রেণি তৈরি করা উচিত।


49
"তবে তাদের ক্লাসের মতো উদাহরণ পদ্ধতি নেই"। ভাল, এটি একটি "সাধারণ শ্রেণি" হিসাবে ব্যবহার করার জন্য একটি সাধারণ প্রচলিত প্যাটার্ন রয়েছে:class Point < Struct.new(:x, :y); methods here; end
টোকল্যান্ড

10
আজকের মতো টোকল্যান্ড, পদ্ধতিগুলি সহ কাঠামোটিকে অনুকূলিতকরণের "পছন্দসই" পদ্ধতির म्हणजे ব্লকটি কনস্ট্রাক্টরে পাস করা Point = Struct.new(:x, :y) { methods here }। ( উত্স ) অবশ্যই, { ... }সেখানে একটি বহু-লাইন ব্লক ( do ... end) লেখা যেতে পারে এবং আমি মনে করি, এটি পছন্দসই উপায়।
ইভান কলমিচেক

1
@ ইভানকোলমিচেক: শীতল, আসলে আমি ব্লক পদ্ধতির পছন্দ করি।
টোকল্যান্ড

@ টোকল্যান্ড ভাল আমি কেবল এটি স্পষ্ট করে বলতে চেয়েছিলাম যে এখন আপনার মতামতটি যেমন আপত্তিজনকভাবে প্রকাশিত হয়েছে, ততক্ষণে রুবিতে নতুন লোকেরা ভাবতে পারে "ঠিক আছে, সুতরাং এটি কীভাবে করা উচিত," কারণ সবাই এর সাথে একমত হয়, ডান ? " :)
ইভান কলমিচেক

4
একটি প্রশ্ন: আপনি একবার আপনার স্ট্রাক্টগুলিতে পদ্ধতি যুক্ত করতে চান এমন মুহুর্তে পৌঁছে আপনি কেন একটি ক্লাস ব্যবহার করবেন না?
jaydel

82

অন্যান্য মানদণ্ড:

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)

5
রুবি 2.14 এর সাথে পার্থক্যটি ছোট 0.94-0.97 ওপেনস্ট্রাক্ট বনাম 0.02-0.03 সাথে অস্ট্রাস্ট্রের (এমবি প্রো 2.2 গিগাহার্টজ আই 7)
বেসেক্স

1
ওপেনস্ট্রাক্ট স্ট্রাক্ট ব্যবহারের গতির সমতুল্য। স্ট্যাকওভারফ্লো . com/a/43987844/128421 দেখুন ।
টিন ম্যান

57

হালনাগাদ:

রুবি ২.৪.১ হিসাবে ওপেনস্ট্রাক্ট এবং স্ট্রাক্ট গতিতে অনেক বেশি কাছাকাছি। Https://stackoverflow.com/a/43987844/128421 দেখুন

পূর্বে:

সম্পূর্ণতার জন্য: স্ট্রাক্ট বনাম ক্লাস বনাম হ্যাশ বনাম ওপেনস্ট্রাক্ট

রুবি ১.৯.২, (৪ টি কোরের x86_64 এর মধ্যে 1 টি, 8 জিবি র‌্যাম) তে একই জাতীয় কোড বার্টলো হিসাবে চালানো [কলামগুলি সারিবদ্ধ করার জন্য সারণী সম্পাদিত]:

1 টি মিও স্ট্রাক্ট তৈরি করছে: 1.43 সেকেন্ড, 219 এমবি / 90 এমবি (পুণ্য / পুনরায়)
1 টি মিও ক্লাসের উদাহরণ তৈরি করছে: 1.43 সেকেন্ড, 219 এমবি / 90 এমবি (পুণ্য / পুনরায়)
1 টি মিও হ্যাশ তৈরি করছে: 4.46 সেকেন্ড, 493 এমবি / 364 এমবি (গুণ / পুনরায়)
1 মিও ওপেনস্ট্রাক্টস তৈরি করা হচ্ছে: 415.13 সেকেন্ড, 2464 এমবি / 2.3 জিবি (গুণ / পুনরায়) # হ্যাশগুলির তুলনায় # ~ 100x কম
100 কে ওপেনস্ট্রাক্টস তৈরি করা হচ্ছে: 10.96 সেকেন্ড, 369 এমবি / 242 এমবি (গুণ / পুনরায়)

ওপেনস্ট্রাক্টগুলি স্লুওউও এবং মেমরি নিবিড় , এবং বড় ডেটা সেটগুলির জন্য ভাল স্কেল করে না

1 মায়ো OpenStructs তৈরি করছে ~ 100x তুলনায় ধীর 1 মায়ো তৈরি হ্যাশ

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
হাই @ টিলো, আপনি কি ফলাফলগুলি পেতে আপনার কোডটি ভাগ করে নিতে পারেন? আমি এটি হ্যাশি :: ম্যাশের সাথে স্ট্রাক্ট এবং ওএসস্ট্রাক্টের তুলনা করতে ব্যবহার করতে চাই। ধন্যবাদ।
ডনি কুরনিয়া

1
আরে @ ডনি, আমি কেবলমাত্র উত্সাহটি দেখেছি এবং বুঝতে পেরেছি যে এটি ২০১১ সালে পরিমাপ করা হয়েছিল - রুবি ২.১ দিয়ে আমার এটি পুনরায় চালানো দরকার: পি আমার কাছে এই কোডটি আছে কিনা তা নিশ্চিত নন, তবে এটি পুনরুত্পাদন করা সহজ হওয়া উচিত। আমি শীঘ্রই এটি ঠিক করার চেষ্টা করব।
টিলো

2
রুবি ২.৪.১ হিসাবে ওপেনস্ট্রাক্ট এবং স্ট্রাক্ট গতিতে অনেক বেশি কাছাকাছি। স্ট্যাকওভারফ্লো.com
টিন ম্যান

34

দুজনের ব্যবহারের ক্ষেত্রে বিষয়টি বেশ আলাদা।

আপনি রুবি ১.৯ এর স্ট্রাক্ট ক্লাসটি structসি এর ঘোষণার সমতুল্য হিসাবে ভাবতে পারেন রুবি ইন Struct.newআর্গুমেন্ট হিসাবে ক্ষেত্রের নামগুলির একটি সেট নেয় এবং একটি নতুন ক্লাস দেয় returns একইভাবে, সি তে, একটি structঘোষণাপত্র ক্ষেত্রগুলির একটি সেট নেয় এবং প্রোগ্রামারকে নতুন জটিল ধরণের ব্যবহার করতে দেয় যেমন তার কোনও বিল্ট-ইন টাইপ থাকে।

রুবি:

Newtype = Struct.new(:data1, :data2)
n = Newtype.new

সি:

typedef struct {
  int data1;
  char data2;
} newtype;

newtype n;

ওপেনস্ট্রাক্ট ক্লাসটি সি এর সাথে একটি বেনামি স্ট্রাক্ট ঘোষণার সাথে তুলনা করা যেতে পারে যা প্রোগ্রামারকে একটি জটিল ধরণের উদাহরণ তৈরি করতে দেয় ।

রুবি:

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;

এখানে কিছু সাধারণ ব্যবহারের মামলা রয়েছে।

ওপেনস্ট্রাক্টস হ্যাশগুলি সহজেই এক-অফ-অবজেক্টগুলিতে রূপান্তর করতে ব্যবহার করা যেতে পারে যা সমস্ত হ্যাশ কীগুলিতে সাড়া দেয়।

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

3
এটি তাদের মধ্যে ধারণাগত পার্থক্যের একটি দুর্দান্ত উত্তর। ওপেনস্ট্রাক্টের নাম প্রকাশ না করার জন্য ধন্যবাদ, আমি মনে করি এটি এটিকে আরও অনেক স্পষ্ট করে তুলেছে।
ব্রায়ান্ট

দুর্দান্ত ব্যাখ্যা!
ইউরি ঘেনসেভ

24

ওপেনস্ট্রাক্টস উল্লেখযোগ্যভাবে আরও মেমরি ব্যবহার করে এবং স্ট্রাক্টের তুলনায় ধীর পারফর্মার।

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 এমবি মেমরি গ্রহণ করেছে med


3
তবে আপনি সচেতন যে ওপেনস্ট্রাক্ট পরীক্ষাটি অনেকগুলি অস্থায়ী হ্যাশ তৈরি করে। আমি কিছুটা পরিবর্তিত বেঞ্চমার্কের পরামর্শ দিচ্ছি - যা এখনও আপনার রায় সমর্থন করে (নীচে দেখুন)।
রবার্ট ক্লেমে

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

উদাহরণের জন্য ধন্যবাদ। এটি অনুশীলনে বুঝতে অনেক সহায়তা করে।
আহসান

5

নতুন পদ্ধতির বিষয়ে API এ দেখুন। সেখানে অনেক পার্থক্য পাওয়া যায়।

ব্যক্তিগতভাবে, আমি বেশ ওপেনস্ট্রাক্টকে পছন্দ করি, কারণ আমার আগে অবজেক্টের কাঠামো সংজ্ঞায়িত করতে হবে না, এবং আমার ইচ্ছে মতো স্টাফ যুক্ত করতে হবে। আমি অনুমান করি যে এটির মূল (ডিস) সুবিধা হবে?


3

@ রবার্ট কোড ব্যবহার করে আমি হাশি :: ম্যাসকে মাপদণ্ডের আইটেমটিতে যুক্ত করেছি এবং এই ফলাফলটি পেয়েছি:

                           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)

আপনার মানদণ্ডটি সত্যিই অদ্ভুত। আমি একটি আই 5 ম্যাক এ রুবি 2.1.1 এর সাথে নিম্নলিখিত ফলাফল পেয়েছি: gist.github.com/nicolas-besnard/…
cappie013

ঠিক আছে, ফলাফলটি ব্যবহার করা রুবি সংস্করণ এবং এটি চালানোর জন্য ব্যবহৃত হার্ডওয়ারের মধ্যে পরিবর্তিত হবে। তবে প্যাটার্নটি এখনও একই, ওপেনস্ট্রাক্ট সবচেয়ে ধীর এবং স্ট্রাক্ট সবচেয়ে দ্রুত test মাঝখানে পড়ে হ্যাশি।
ডোনি করনিয়া

0

আসলে প্রশ্নের উত্তর নয়, তবে আপনি যদি পারফরম্যান্সের বিষয়ে চিন্তা করেন তবে খুব গুরুত্বপূর্ণ বিবেচনা । দয়া করে লক্ষ্য করুন যে আপনি যখনই কোনও OpenStructঅপারেশন তৈরি করবেন তখন পদ্ধতি ক্যাশে সাফ করে, যার অর্থ আপনার অ্যাপ্লিকেশনটি ধীর গতিতে কাজ করবে। মন্দতা বা না হওয়া OpenStructকেবল এটি নিজের দ্বারা কীভাবে কাজ করে তা নয়, তবে এগুলি ব্যবহার করে যে সমস্ত প্রভাবগুলি পুরো প্রয়োগটিতে আসে: https://github.com/charliesome/charlie.bz/blob/master/posts/things-that -clear-rubys-method-cache.md # openstructs

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.