From: ara.t.howard@... Date: 2007-04-04T04:34:00+09:00 Subject: Re: implementing an array based class On Wed, 4 Apr 2007, bwv549 wrote: >> i'd love to see your tests using it. > > Thanks for the insight. I've included an arrayfields implementation > on the above benchmark: > > Rehearsal -------------------------------------------------- > ArrayFields 8.433333 0.800000 9.233333 ( 5.585626) > Class1 5.566667 0.500000 6.066667 ( 3.631757) > Class2 6.050000 0.550000 6.600000 ( 3.963679) > Struct 3.583333 0.300000 3.883333 ( 2.335911) > ArrayBased 2.033333 0.266667 2.300000 ( 1.381698) > Array.new 1.950000 0.333333 2.283333 ( 1.371351) > Array [] 0.833333 0.316667 1.150000 ( 0.689010) > ---------------------------------------- total: 31.516667sec > > user system total real > ArrayFields 8.516667 0.816667 9.333333 ( 5.609708) > Class1 5.366667 0.650000 6.016667 ( 3.617349) > Class2 5.933333 0.566667 6.500000 ( 3.893614) > Struct 3.616667 0.266667 3.883333 ( 2.360849) > ArrayBased 1.933333 0.316667 2.250000 ( 1.374079) > Array.new 1.883333 0.333333 2.216667 ( 1.370410) > Array [] 0.866667 0.283333 1.150000 ( 0.696223) > > > Here's how I tested it (let me know if this is done incorrectly): > > require 'arrayfields' > fields = %w(f1 f2 f3 f4 f5 f6 f7) > > bmbm(15) do |re| > re.report("ArrayFields") { REP.times { x = [*attribute_array]; > x.fields = fields } } > ## .... same as before > end > > I haven't tested the memory on it, but it would appear to be comparable to > an Array (very low memory usage) from your implementation. It does have > slightly higher overhead in the time required for creation (if I did it > correctly). Nonetheless, arrayfields seems ideal for database work as you > can simply label the fields without creating new classes for everything. In > the particular case before me, I have only a handful of object types, but > lots of them. seems like you're realy comparing apples to oranges here. for instance your Class1 contructor only every takes a copy of 'attribute_array', while some ctors take copies, or even several. i made a mod so all calles to attribute_array created a new array so you can actually measure the speed of the ctor not the speed of copying vs not copying an array (we know which one is faster!). and not all your implimentations provide keyword access - but i guess you know that... also i used the new (version 3.7.0) arrayfields interface to build a class that way. here are the results harp:~ > cat a.rb #! /usr/bin/env ruby require 'rubygems' require 'arrayfields' # 3.7.0! require 'benchmark' include Benchmark class Class1 def initialize(attribute_array) (@f1, @f2, @f3, @f4, @f5, @f6, @f7) = attribute_array end end class Class2 def initialize(f1=nil, f2=nil, f3=nil, f4=nil, f5=nil, f6=nil, f7=nil) @f1=f1 @f2=f2 @f3=f3 @f4=f4 @f5=f5 @f6=f6 @f7=f7 end end StructClass = Struct.new(:f1, :f2, :f3, :f4, :f5, :f6, :f7) class ArrayBased < Array end =begin # # this is all Array.fields does # class ArrayFieldsBased < Array FIELDS = ArrayFields::FieldSet.new [:f1, :f2, :f3, :f4, :f5, :f6, :f7] include ArrayFields def initialize *a, &b super ensure @fieldset = FIELDS end end =end ArrayFieldsBased = Array.fields :f1, :f2, :f3, :f4, :f5, :f6, :f7 def attribute_array() (1..7).to_a end REP = 1_000_00 #_000 bmbm(15) do |re| re.report("ArrayFieldsBased") { REP.times { ArrayFieldsBased.new attribute_array } } re.report("Class1") { REP.times { Class1.new attribute_array } } re.report("Class2") { REP.times { Class2.new *attribute_array} } re.report("Struct") { REP.times { StructClass.new *attribute_array } } re.report("ArrayBased") { REP.times { ArrayBased.new attribute_array } } re.report("Array.new") { REP.times { Array.new attribute_array } } re.report("Array []") { REP.times { [*attribute_array] } } end and here's the results [ahoward@localhost ~]$ ruby a.rb Rehearsal ---------------------------------------------------- ArrayFieldsBased 1.440000 0.010000 1.450000 ( 1.709076) Class1 1.550000 0.020000 1.570000 ( 6.274899) Class2 1.680000 0.000000 1.680000 ( 1.945875) Struct 1.230000 0.010000 1.240000 ( 1.486386) ArrayBased 1.000000 0.000000 1.000000 ( 1.309320) Array.new 0.980000 0.000000 0.980000 ( 1.178536) Array [] 0.750000 0.000000 0.750000 ( 0.935874) ------------------------------------------- total: 8.670000sec user system total real ArrayFieldsBased 1.560000 0.000000 1.560000 ( 1.787502) Class1 1.400000 0.010000 1.410000 ( 1.627891) Class2 1.480000 0.000000 1.480000 ( 1.742301) Struct 1.180000 0.010000 1.190000 ( 1.299734) ArrayBased 0.970000 0.000000 0.970000 ( 1.050021) Array.new 0.980000 0.000000 0.980000 ( 1.089647) Array [] 0.740000 0.010000 0.750000 ( 0.888502) so, now you see what you should - all approaches are within the same order of magnitude: there is no difference. regards. -a -- be kind whenever possible... it is always possible. - the dalai lama