Hacking Ruby Hash: Fastest #to_struct method
Use OpenHash and Ruby >= 2.3.0

Starting with MRI 2.3.0, your benchmark using OpenHash gets fast.  Very fast:

ruby-2.2.5: ruby 2.2.5p319 (2016-04-26 revision 54774) [x86_64-linux]
       user     system      total        real
#to_struct  1.780000   0.000000   1.780000 (  1.774490)
Struct  9.100000   0.000000   9.100000 (  9.099619)
OpenStruct  7.910000   0.000000   7.910000 (  7.911342)

ruby-2.3.0: ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
       user     system      total        real
#to_struct  1.700000   0.000000   1.700000 (  1.695587)
Struct  7.660000   0.000000   7.660000 (  7.660869)
OpenStruct  0.650000   0.000000   0.650000 (  0.658817)


With the latest MRI, Your #to_struct method gets a bit of a speed boost as well.

ruby-2.4.1: ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
       user     system      total        real
#to_struct  1.460000   0.000000   1.460000 (  1.459063)
Struct  7.420000   0.000000   7.420000 (  7.416505)
OpenStruct  0.660000   0.000000   0.660000 (  0.658009)


So if you can, use Ruby >= ruby 2.3.0, and use OpenHash.

How to make #to_struct faster

I made the following changes for performance:


Eliminate the mapping of hash keys using #downcase.
Use #values instead of #values_at (values are always the same order as keys).  See https://stackoverflow.com/a/31425274/238886


and these for clarity:


Eliminate the temporary for self.keys
DRY the creation of the struct instance
Removed self references.


With these changes, the code is:

class Hash
  def new_to_struct
    klass_name = keys.map(&amp;:to_s).sort.join.capitalize
    klass = begin
              Kernel.const_get("Struct::" + klass_name)
            rescue NameError
              Struct.new(klass_name, *keys)
            end
    klass.new(*values)
  end
end


and the benchmark (run against ruby-2.4.1):

       user     system      total        real
#to_struct  1.410000   0.000000   1.410000 (  1.403908)
#new_to_struct  0.760000   0.000000   0.760000 (  0.757548)
Struct  7.060000   0.010000   7.070000 (  7.075619)
OpenStruct  0.650000   0.000000   0.650000 (  0.649057)


These changes get to_struct close to OpenStruct, but still not as fast.