From: John Carter Date: 2005-09-26T10:22:16+09:00 Subject: SUMMARY: Switching invariant check in or out. Ok, so there seems to be three basic methods of doing this, the most hairy involves using class_eval to interpose an aspect on function call and return. Cute. Scary. Anywhoo, the other two are basically to make the invariant method empty or to only invoke the invariant method if a global or const is true.... require 'benchmark' DEBUG = false $foo = false class A attr_reader :inv alias_method :in_very_ant, :object_id def invariant end def very in_very_ant in_very_ant end def empty_method invariant invariant end def if_const invariant if DEBUG invariant if DEBUG end def if_global invariant if $foo invariant if $foo end def attr_thing inv inv end def no_code end end n = 1000000 a = A.new Benchmark.benchmark(" "*7 + Benchmark::CAPTION, 7, Benchmark::FMTSTR, ">total:", ">avg:") do |x| tf = x.report("empty_method:") { n.times do ; a.empty_method; end } tt = x.report("if_const:") { n.times do ; a.if_const ; end } tg = x.report("if_global:") { n.times do ; a.if_const ; end } tu = x.report("no_code:") { n.times do ; a.no_code ; end } tv = x.report("inv:") { n.times do ; a.attr_thing ; end } tw = x.report("very:") { n.times do ; a.very ; end } x.report("nothin:") { n.times do ; a ; end } [tf+tt+tg+tu+tv+tw, (tf+tt+tg+tu+tv+tw)/6] end The results are using Ruby 1.8.2... ruby-1.8.2 binch.rb;ruby binch.rb user system total real empty_method: 1.210000 0.000000 1.210000 ( 1.218951) if_const: 1.010000 0.000000 1.010000 ( 1.016450) if_global: 1.020000 0.000000 1.020000 ( 1.021371) no_code: 0.580000 0.000000 0.580000 ( 0.584446) inv: 0.850000 0.000000 0.850000 ( 0.852560) very: 0.870000 0.000000 0.870000 ( 0.863922) nothin: 0.260000 0.010000 0.270000 ( 0.261910) >total: 5.540000 0.000000 5.540000 ( 5.557700) >avg: 0.923333 0.000000 0.923333 ( 0.926283) And a fairly recent version from CVS.... user system total real empty_method: 1.160000 0.000000 1.160000 ( 1.159409) if_const: 0.950000 0.000000 0.950000 ( 0.953207) if_global: 0.970000 0.000000 0.970000 ( 0.972160) no_code: 0.570000 0.000000 0.570000 ( 0.569933) inv: 0.790000 0.000000 0.790000 ( 0.789721) very: 0.800000 0.000000 0.800000 ( 0.796247) nothin: 0.260000 0.000000 0.260000 ( 0.266906) >total: 5.240000 0.000000 5.240000 ( 5.240677) >avg: 0.873333 0.000000 0.873333 ( 0.873446) notes: 1) I was surprised to find the if const and if global so close. Obviously no constant folding is being done on branches. 2) Of course, no code is faster than no code. So the hairy class_eval tricks would be faster. Although not tremendously faster than the attr_reader trick. 3) Ruby 1.9 is noticably faster than 1.8.2 Thanks for all the responses and wild creativity. 4) Ruby-contract, Awesome and ruby-dbc are very very very scary modules. I'm not sure I can cope with anything quite that clever near my code. It has all (and more, much more) the horror of the C preprocessor, without the gcc -E option to see the what it actually did. John Carter Phone : (64)(3) 358 6639 Tait Electronics Fax : (64)(3) 359 4632 PO Box 1645 Christchurch Email : john.carter@tait.co.nz New Zealand Carter's Clarification of Murphy's Law. "Things only ever go right so that they may go more spectacularly wrong later." From this principle, all of life and physics may be deduced.