When should I use Struct vs. OpenStruct?

后端 未结 9 1151
孤城傲影
孤城傲影 2020-11-28 00:35

In general, what are the advantages and disadvantages of using an OpenStruct as compared to a Struct? What type of general use-cases would fit each of these?

相关标签:
9条回答
  • 2020-11-28 01:26

    UPDATE:

    As of Ruby 2.4.1 OpenStruct and Struct are much closer in speed. See https://stackoverflow.com/a/43987844/128421

    PREVIOUSLY:

    For completeness: Struct vs. Class vs. Hash vs. OpenStruct

    Running similar code as burtlo's, on Ruby 1.9.2, (1 of 4 cores x86_64, 8GB RAM) [table edited to align columns]:

    creating 1 Mio Structs :         1.43 sec ,  219 MB /  90MB (virt/res)
    creating 1 Mio Class instances : 1.43 sec ,  219 MB /  90MB (virt/res)
    creating 1 Mio Hashes  :         4.46 sec ,  493 MB / 364MB (virt/res)
    creating 1 Mio OpenStructs :   415.13 sec , 2464 MB / 2.3GB (virt/res) # ~100x slower than Hashes
    creating 100K OpenStructs :     10.96 sec ,  369 MB / 242MB (virt/res)
    

    OpenStructs are sloooooow and memory intensive , and don't scale well for large data sets

    Creating 1 Mio OpenStructs is ~100x slower than creating 1 Mio Hashes.

    start = Time.now
    
    collection = (1..10**6).collect do |i|
      {:name => "User" , :age => 21}
    end; 1
    
    stop = Time.now
    
    puts "#{stop - start} seconds elapsed"
    
    0 讨论(0)
  • 2020-11-28 01:33

    Other benchmark:

    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
    

    For the impatient who wants to get an idea of the benchmark results, without running them themselves, here is the output of the code above (on an 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)
    
    0 讨论(0)
  • 2020-11-28 01:40

    Not actually an answer to the question, but a very important consideration if you care about performance. Please notice that every time you create an OpenStruct the operation clears the method cache, which means your application will perform slower. The slowness or not of OpenStruct is not just about how it works by itself, but the implications that using them bring to the whole application: https://github.com/charliesome/charlie.bz/blob/master/posts/things-that-clear-rubys-method-cache.md#openstructs

    0 讨论(0)
提交回复
热议问题