When is it better to use a Struct rather than a Hash in Ruby?

前端 未结 6 1225
清歌不尽
清歌不尽 2021-01-30 20:44

A Ruby Struct allows an instance to be generated with a set of accessors:

# Create a structure named by its constant
Customer = Struct.new(:name, :address)     #         


        
6条回答
  •  北恋
    北恋 (楼主)
    2021-01-30 21:08

    Here is more readable benchmarks for those who loves IPS(iteration per seconds) metrics:

    For small instances:

    require 'benchmark/ips'
    require 'ostruct'
    
    MyStruct = Struct.new(:a)
    Benchmark.ips do |x|
      x.report('hash') { a = { a: 1 }; a[:a] }
      x.report('struct') { a = MyStuct.new(1); a.a }
      x.report('ostruct') { a = OpenStruct.new(a: 1); a.a }
    
      x.compare!
    end
    

    results:

    Warming up --------------------------------------
                    hash   147.162k i/100ms
                  struct   171.949k i/100ms
                 ostruct    21.086k i/100ms
    Calculating -------------------------------------
                    hash      2.608M (± 3.1%) i/s -     13.097M in   5.028022s
                  struct      3.680M (± 1.8%) i/s -     18.399M in   5.001510s
                 ostruct    239.108k (± 5.5%) i/s -      1.202M in   5.046817s
    
    Comparison:
                  struct:  3679772.2 i/s
                    hash:  2607565.1 i/s - 1.41x  slower
                 ostruct:   239108.4 i/s - 15.39x  slower
    

    For huge list:

    require 'benchmark/ips'
    require 'ostruct'
    
    MyStruct = Struct.new(:a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l, :m, :n, :o, :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z)
    
    Benchmark.ips do |x|
      x.report('hash') do
        hash = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10, k: 11, l: 12, m: 13, n: 14, o: 15, p: 16, q: 17, r: 18, s: 19, t: 20, u: 21, v: 22, w: 23, x: 24, y: 25, z: 26 }
        hash[:a]; hash[:b]; hash[:c]; hash[:d]; hash[:e]; hash[:f]; hash[:g]; hash[:h]; hash[:i]; hash[:j]; hash[:k]; hash[:l]; hash[:m]; hash[:n]; hash[:o]; hash[:p]; hash[:q]; hash[:r]; hash[:s]; hash[:t]; hash[:u]; hash[:v]; hash[:w]; hash[:x]; hash[:y]; hash[:z]
      end
    
      x.report('struct') do
        struct = MyStruct.new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)
        struct.a;struct.b;struct.c;struct.d;struct.e;struct.f;struct.g;struct.h;struct.i;struct.j;struct.k;struct.l;struct.m;struct.n;struct.o;struct.p;struct.q;struct.r;struct.s;struct.t;struct.u;struct.v;struct.w;struct.x;struct.y;struct.z
      end
    
      x.report('ostruct') do
        ostruct = OpenStruct.new( a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10, k: 11, l: 12, m: 13, n: 14, o: 15, p: 16, q: 17, r: 18, s: 19, t: 20, u: 21, v: 22, w: 23, x: 24, y: 25, z: 26)
        ostruct.a;ostruct.b;ostruct.c;ostruct.d;ostruct.e;ostruct.f;ostruct.g;ostruct.h;ostruct.i;ostruct.j;ostruct.k;ostruct.l;ostruct.m;ostruct.n;ostruct.o;ostruct.p;ostruct.q;ostruct.r;ostruct.s;ostruct.t;ostruct.u;ostruct.v;ostruct.w;ostruct.x;ostruct.y;ostruct.z;
      end
    
      x.compare!
    end
    

    results:

    Warming up --------------------------------------
                    hash    51.741k i/100ms
                  struct    62.346k i/100ms
                 ostruct     1.010k i/100ms
    Calculating -------------------------------------
                    hash    603.104k (± 3.9%) i/s -      3.053M in   5.070565s
                  struct    780.005k (± 3.4%) i/s -      3.928M in   5.041571s
                 ostruct     11.321k (± 3.4%) i/s -     56.560k in   5.001660s
    
    Comparison:
                  struct:   780004.8 i/s
                    hash:   603103.8 i/s - 1.29x  slower
                 ostruct:    11321.2 i/s - 68.90x  slower
    

    Conclusion

    As you can see struct is a little bit faster, but it requires to define struct fields before using it, so if performance is really matter for you use struct ;)

提交回复
热议问题