200 votes

Ruby: Struct vs OpenStruct

En général, quels sont les avantages et les inconvénients de l'utilisation d'un OpenStruct par rapport à une Structure? Ce type de l'utilisation générale des cas, correspondent à chacun de ces?

188voto

Pesto Points 16648

Avec un OpenStruct, vous pouvez créer artificiellement des attributs. Une Structure, d'autre part, doit avoir ses attributs définis lors de sa création. Le choix de l'un sur l'autre devrait être fondée principalement sur si vous devez être en mesure d'ajouter des attributs plus tard.

La façon de penser est que le milieu de terrain du spectre entre les Hachages d'un côté et des cours sur l'autre. Ils impliquent une plus concrète de la relation entre les données de Hachage, mais ils n'ont pas les méthodes d'instance comme le ferait une classe. Un tas d'options pour une fonction, par exemple, a de sens que dans une table de hachage; ils ne sont que vaguement liés. Un nom, courriel et numéro de téléphone requis par une fonction pourrait être emballés ensemble dans une Structure ou OpenStruct. Si ce nom, courriel et numéro de téléphone requis méthodes pour fournir le nom dans les deux "prénom" et "nom, prénom" formats, vous devez créer une classe permettant de gérer.

82voto

Robert Klemme Points 1244

Autre indice:

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

Pour les impatients qui veut avoir une idée de l'indice de référence des résultats, sans les exécuter eux-mêmes, ici, c'est la sortie du code ci-dessus (sur un MB Pro 2.4 GHz 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)

58voto

Tilo Points 13833

Pour être complet: Struct vs Hachage vs OpenStruct vs Classe

L'exécution de code similaire comme burtlo, sur Ruby 1.9.2, (1 des 4 cœurs x86_64, 8 go de RAM):

la création de 1 Mio Structures : 1.43 sec , 219MB / 90 MO (virt/res)
la création de 1 Mio instances de Classe : 1.43 sec , 219MB / 90 MO (virt/res)
la création de 1 Mio de Hachages : 4.46 sec , 493 MO / 364MB (virt/res)
la création de 1 Mio OpenStructs : 415.13 sec , 2464 MO / 2.3 GO (virt/res) # ~100 fois plus lent que les Hachages
la création de 100K OpenStructs : 10.96 sec , 369 MO , 242 MO (virt/res)

OpenStructs sont sloooooow et les plus gourmands en mémoire , et n'est pas à l'échelle de grands ensembles de données

La création de 1 Mio OpenStructs est de ~100 fois plus lent que la création de 1 Mio de Hachages.

start = Time.now

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

stop = Time.now

puts "#{stop - start} seconds elapsed"

30voto

Robert Klemme Points 1244

J'ai quelques remarques à propos de Struct vs OpenStruct vs Hachage dans mon récent commentaire de blog "les Structures à l'intérieur", juste au cas où quelqu'un est intéressé.

24voto

burtlo Points 821

OpenStructs utiliser beaucoup plus de mémoire et sont plus lents artistes interprètes ou exécutants contre des Structures.

require 'ostruct' 

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

Sur mon système, le code suivant exécuté en 14 secondes et consommé 1,5 GO de mémoire. Votre kilométrage peut varier:

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

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

Qui fini presque instantanément et consommé de 26,6 MO de mémoire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X