[ruby] Struct와 OpenStruct는 언제 사용해야합니까?

일반적으로 Struct와 비교하여 OpenStruct를 사용하는 경우의 장단점은 무엇입니까? 이들 각각에 적합한 일반적인 유스 케이스 유형은 무엇입니까?



답변

을 사용하면 OpenStruct임의로 속성을 만들 수 있습니다. ㅏStruct 당신이 그것을 만들 때, 다른 한편으로는, 그 속성이 정의되어 있어야합니다. 둘 중 하나의 선택은 기본적으로 나중에 속성을 추가 할 수 있어야하는지에 따라 결정되어야합니다.

그것들을 생각하는 방법은 한쪽의 해시와 다른 쪽의 클래스 사이의 스펙트럼의 중간 근거입니다. 그것들은 데이터보다 더 구체적인 관계를 암시 Hash하지만 클래스와 같은 인스턴스 메소드는 없습니다. 예를 들어 함수에 대한 많은 옵션은 해시에서 의미가 있습니다. 그들은 느슨하게 관련되어 있습니다. 기능에 필요한 이름, 이메일 및 전화 번호는 Struct또는로 함께 패키지 될 수 있습니다 OpenStruct. 해당 이름, 전자 메일 및 전화 번호에 “처음”형식과 “성, 이름”형식으로 이름을 제공하는 방법이 필요한 경우 처리 할 클래스를 만들어야합니다.


답변

다른 벤치 마크 :

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)


답변

최신 정보:

Ruby 2.4.1부터 OpenStruct와 Struct는 속도가 훨씬 더 가깝습니다. 참조 https://stackoverflow.com/a/43987844/128421를

이전 :

완전성 : Struct vs. Class vs. Hash vs. OpenStruct

Ruby 1.9.2에서 burtlo와 유사한 코드 실행 (4 개의 코어 중 1 개 x86_64, 8GB RAM) [테이블을 정렬하여 열 정렬] :

1 Mio Structs 생성 : 1.43 초, 219MB / 90MB (virt / res)
1 개의 Mio 클래스 인스턴스 생성 : 1.43 초, 219MB / 90MB (virt / res)
1 개의 Mio Hashes 생성 : 4.46 초, 493MB / 364MB (virt / res)
Mio OpenStructs 1 개 생성 : 415.13 초, 2464MB / 2.3GB (virt / res) # ~ 100 배 느리다
100K OpenStructs 생성 : 10.96 초, 369MB / 242MB (virt / res)

OpenStructs는 빈약 하고 메모리 집약적 이며 대용량 데이터 세트에는 적합하지 않습니다.

1 Mio OpenStructs 생성은 1 Mio Hashes 생성 보다 ~ 100 배 느립니다 .

start = Time.now

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

stop = Time.now

puts "#{stop - start} seconds elapsed"


답변

두 가지 사용 사례는 상당히 다릅니다.

Ruby 1.9의 Struct 클래스는 structC 의 선언 과 동일하다고 생각할 수 있습니다 . Ruby에서는 Struct.new필드 이름 세트를 인수로 사용하여 새 클래스를 리턴합니다. 마찬가지로 C에서 struct선언은 필드 세트를 사용하여 프로그래머가 내장 유형과 마찬가지로 새로운 복합 유형을 사용할 수 있도록합니다.

루비:

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

씨:

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

newtype n;

OpenStruct 클래스는 C의 익명 구조체 선언과 비교할 수 있습니다. 프로그래머가 복잡한 유형 의 인스턴스 를 만들 수 있습니다 .

루비:

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

Structs는 속기 클래스 정의에 유용 할 수 있습니다.

class MyClass < Struct.new(:a,:b,:c)
end

m = MyClass.new
m.a = 1


답변

OpenStructs는 훨씬 더 많은 메모리를 사용하며 Structs보다 성능이 느립니다.

require 'ostruct'

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

내 시스템에서 다음 코드는 14 초 안에 실행되었고 1.5GB의 메모리를 소비했습니다. 마일리지가 다를 수 있습니다 :

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

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

거의 즉시 완료되었고 26.6MB의 메모리를 사용했습니다.


답변

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


답변

새로운 메소드와 관련하여 API를 살펴보십시오. 많은 차이점이 있습니다.

개인적으로 객체의 구조를 미리 정의 할 필요가없고 원하는대로 항목을 추가 할 필요가 없기 때문에 OpenStruct를 매우 좋아합니다. 나는 그것이 주요 (단점) 이점이 될 것이라고 생각합니까?