web-dev-qa-db-ja.com

StructとOpenStructをいつ使用する必要がありますか?

一般的に、Structと比較してOpenStructを使用する利点と欠点は何ですか?どのタイプの一般的なユースケースがこれらのそれぞれに適合しますか?

177
ehsanul

OpenStructを使用すると、属性を任意に作成できます。一方、Structは、作成時に属性を定義する必要があります。どちらを選択するかは、主に後で属性を追加できるようにする必要があるかどうかに基づいて決定する必要があります。

それらについて考える方法は、一方のハッシュと他方のクラスとの間のスペクトルの中間点としてです。これらは、Hashの場合よりもデータ間のより具体的な関係を意味しますが、クラスのようにインスタンスメソッドはありません。たとえば、関数の一連のオプションはハッシュで意味があります。それらは大まかに関連しているだけです。関数に必要な名前、電子メール、および電話番号は、StructまたはOpenStructに一緒にパッケージ化できます。その名前、電子メール、および電話番号に、名前を「First Last」と「Last、First」の両方の形式で提供するメソッドが必要な場合、それを処理するクラスを作成する必要があります。

167
Pesto

その他のベンチマーク:

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

ベンチマーク結果を自分で実行せずに把握したいせっかちな人向けに、上記のコードの出力を示します(MB Pro 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)
82
Robert Klemme

UPDATE:

Ruby 2.4.1 OpenStructとStructの速度ははるかに近い。 https://stackoverflow.com/a/43987844/128421 を参照

以前:

完全を期すために:Structvs.Classvs.ハッシュvs.OpenStruct

Ruby 1.9.2、(4コアx86_64の1つ、8GB RAM)] [列を揃えるために編集されたテーブル]で、burtloのコードと同様のコードを実行します。

 1 Mio Structsの作成:1.43秒、219 MB/90MB(virt/res)
 1 Mioクラスインスタンスの作成:1.43秒、219 MB/90MB(virt/res)
 1 Mioハッシュの作成:4.46秒、493 MB/364MB(virt/res)
 1 Mio OpenStructsの作成:415.13秒、2464 MB/2.3GB(virt/res)#ハッシュ[.____。よりも100倍遅い。 ] 10万個のOpenStructsの作成:10.96秒、369 MB/242MB(virt/res)

OpenStructsは、sloooooowおよびメモリ集中型、および大規模なデータセットに対して適切にスケーリングしない

1つのMio OpenStructsを作成すると、〜100xが遅くなります1つのMioHashesを作成します。

start = Time.now

collection = (1..10**6).collect do |i|
  {:name => "User" , :age => 21}
end; 1

stop = Time.now

puts "#{stop - start} seconds elapsed"
57
Tilo

2つのユースケースはまったく異なります。

Ruby 1.9のStructクラスは、Cのstruct宣言と同等であると考えることができます。InRuby Struct.newは、フィールド名のセットを引数として取り、新しいクラスを返します。同様に、Cでは、struct宣言は一連のフィールドを受け取り、プログラマが組み込み型と同じように新しい複合型を使用できるようにします。

ルビー:

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

C:

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

newtype n;

OpenStructクラスは、Cの匿名のstruct宣言と比較できます。これにより、プログラマは、複合型のinstanceを作成できます。

ルビー:

o = OpenStruct.new(data1: 0, data2: 0) 
o.data1 = 1
o.data2 = 2

C:

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
33
skryl

OpenStructsは大幅に多くのメモリを使用し、Structsよりもパフォーマンスが低下します。

require 'ostruct' 

collection = (1..100000).collect do |index|
   OpenStruct.new(:name => "User", :age => 21)
end

私のシステムでは、次のコードが14秒で実行され、1.5 GBのメモリを消費しました。走行距離は異なる場合があります。

User = Struct.new(:name, :age)

collection = (1..100000).collect do |index|
   User.new("User",21)
end

それはほぼ瞬時に終了し、26.6 MBのメモリを消費しました。

24
burtlo

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
6
Dorian

新しいメソッドに関するAPIをご覧ください。そこには多くの違いがあります。

個人的には、オブジェクトの構造を事前に定義する必要がなく、必要に応じて追加するだけなので、OpenStructは非常に気に入っています。それが主な(不利な)利点になると思いますか?

5
Omar Qureshi

@Robertコードを使用して、ベンチマーク項目にHashie :: Mashを追加し、次の結果を得ました。

                           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)
3
Donny Kurnia